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

Cマガ電脳クラブ(第157回) 肩のせ文字の誤植

問題

「3の4乗・425」はいうまでもなく、「3の4乗に425を掛ける」という意味であるが、
これを間違えて34425と書いても、結果として同じになる。
 3の4乗・425 = 34425

このように、「aのb乗・c」という式で、
肩にのせておくべき数を間違えて並べて書いても結果として同じになるものの中で、
上式の右辺が6桁で成立するものをすべてお答えいただきたい。

なお、すでに成立している式のcの最後に0を付加したもの (上の例では,3の4乗・4250 = 344250) も、
その解の1つであることは明白である。a、b、cは何桁の数であってもよい。
また、各数の左端の数字に0はこないこととする。


ソース

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        for (int A = 2; A <= 9999; A++) {
            if (A * A > 999999) break;
            for (int B = 2; B <= 9999; B++) {
                int KetaA = DeriveKetasuu(A);
                int KetaB = DeriveKetasuu(B);
                int KetaC = 6 - KetaA - KetaB;
                if (KetaA + KetaB > 4) break;

                int BekijyouAB = DeriveBekijyou(A, B);
                if (BekijyouAB > 999999) break;

                //方程式 (AのB乗) * C = (AとBとCを並べた数値) を解く
                int ConcatNumAB = DeriveConcatNum(new int[] { A, B });
                int UhenBunsi = ConcatNumAB;
                for (int I = 1; I <= KetaC; I++) UhenBunsi *= 10;

                int UhenBunbo = BekijyouAB - 1;

                //正でないなら不適
                if (UhenBunsi / UhenBunbo <= 0) continue;
                //整数でないなら不適
                if (UhenBunsi % UhenBunbo > 0) continue;
                int C = UhenBunsi / UhenBunbo;
                //桁数のチェック
                if (DeriveKetasuu(C) != KetaC) continue;

                Console.WriteLine("解を発見。{0}の{1}乗*{2} = {3}", A, B, C, BekijyouAB * C);
            }
        }
    }

    //繰り返し2乗法で、AのB乗を求める
    static int DeriveBekijyou(int pA, int pB)
    {
        int CurrJyousuu = pA;
        int CurrShisuu = 1;
        int WillReturn = 1;

        while (true) {
            //対象ビットが立っている場合
            if ((pB & CurrShisuu) > 0) {
                WillReturn *= CurrJyousuu;
            }

            CurrShisuu *= 2;
            if (CurrShisuu > pB) return WillReturn;
            CurrJyousuu *= CurrJyousuu;
        }
    }

    //数値をつなげた数値を返す
    static int DeriveConcatNum(int[] pNumArr)
    {
        var ConcatNumList = new List<int>();
        foreach (int EachInt in pNumArr) {
            List<int> wkNumList = DeriveNumList(EachInt);
            wkNumList.Reverse();
            ConcatNumList.AddRange(wkNumList);
        }

        int ReversedNum = 0;
        foreach (int EachNum in ConcatNumList) {
            ReversedNum *= 10;
            ReversedNum += EachNum;
        }
        return ReversedNum;
    }

    //数値から数字のListを求めて返す
    static List<int> DeriveNumList(int pVal)
    {
        var WillReturn = new List<int>();
        int CopiedVal = pVal;
        do {
            int ModVal = CopiedVal % 10;
            WillReturn.Add(ModVal);
            CopiedVal /= 10;
        } while (CopiedVal > 0);
        return WillReturn;
    }

    //桁数を求める
    static int DeriveKetasuu(int pVal)
    {
        if (pVal <= 9) return 1;
        if (pVal <= 99) return 2;
        if (pVal <= 999) return 3;
        if (pVal <= 9999) return 4;
        if (pVal <= 99999) return 5;
        return 6;
    }
}


実行結果

解を発見。3の4乗*4250 = 344250
解を発見。31の2乗*325 = 312325
解を発見。49の2乗*205 = 492205


解説

AとBが決まれば、Cは方程式を満たすのが必要条件となるので、
方程式を解いてから、十分性をチェックしてます。