トップページに戻る    次のC++のサンプルへ    前のC++のサンプルへ

Problem62 桁の置換をちょうど5つもつ最小の立方数

問題

立方数 41063625は, 桁の順番を入れ替えると2つの立方数になる:
56623104と 66430125である.
41063625は, 立方数になるような桁の置換をちょうど3つもつ最小の立方数である.

立方数になるような桁の置換をちょうど5つもつ最小の立方数を求めよ.


ソース

#include <valarray>
#include <stdio.h>
#include <vector>

//const int kosuu = 3;
const int kosuu = 5;

std::valarray<int> DeriveNumCntArr(__int64 pTarget);
bool CompareArr(const std::valarray<int> &pArr1,const std::valarray<int> &pArr2);

const int BaseJyougen = 10000;

void main()
{
    std::valarray<__int64> SanjyouArr(BaseJyougen+1);
    for(int I=0;I<=BaseJyougen;I++) SanjyouArr[I] = (__int64)I*I*I;

    printf("%dの立方である、\n",BaseJyougen);
    printf("%I64dを立方数の上限として検証します。\n\n",SanjyouArr[BaseJyougen]);

    for (int I=0; I<=(int)SanjyouArr.size()-1; I++) {
        std::valarray<int> NumCntArr1 = DeriveNumCntArr(SanjyouArr[I]);
        std::vector<int> AnswerVect(1,I);

        int cnt = 1;
        for(int J=I+1;J<=(int)SanjyouArr.size()-1;J++){
            std::valarray<int> NumCntArr2 = DeriveNumCntArr(SanjyouArr[J]);

            //桁数が異なる場合
            if(NumCntArr1.sum() > NumCntArr2.sum()) continue;
            if(NumCntArr1.sum() < NumCntArr2.sum()) break;

            if(CompareArr(NumCntArr1,NumCntArr2)){
                AnswerVect.push_back(J);
                if (++cnt > kosuu) break;
            }
        }
        if (cnt == kosuu) {
            printf("Answer=%I64d\n",SanjyouArr[I]);
            puts("立方数の組み合わせは");
            std::vector<int>::iterator it;
            for(it= AnswerVect.begin();it!=AnswerVect.end();it++){
               printf("%I64d(%dの3乗)\n",(__int64)(*it)*(*it)*(*it),*it);
            }
            return;
        }
    }
}

//数字の登場回数を配列にセットして返す
std::valarray<int> DeriveNumCntArr(__int64 pTarget)
{
    std::valarray<int> WillReturn(0,10);
    do {
        int wk = pTarget % 10;
        WillReturn[wk]++;
        pTarget /= 10;
    } while (pTarget > 0);
    return WillReturn;
}

//配列の各要素が一致しているかを判定
bool CompareArr(const std::valarray<int> &pArr1,const std::valarray<int> &pArr2)
{
    for (int I=0; I<=(int)pArr1.size()-1; I++) {
        if(pArr1[I] != pArr2[I]) return false;
    }
    return true;
}


実行結果

10000の立方である、
1000000000000を立方数の上限として検証します。

Answer=127035954683
立方数の組み合わせは
127035954683(5027の3乗)
352045367981(7061の3乗)
373559126408(7202の3乗)
569310543872(8288の3乗)
589323567104(8384の3乗)


解説

立方数の上限を、
1000000000000として、求まった解が
127035954683 ですので題意を満たしてます。