using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
const int LimitQ = 15;
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (long Q = 3; Q <= LimitQ; Q++) {
Console.WriteLine(new string('■', 30));
long LimitP = DeriveLimitP(Q);
var MotodooriSuuList = new List<long>();
for (long P = 2; P <= LimitP; P++) {
if (IsMotodooriSuu(P, Q) == false) continue;
MotodooriSuuList.Add(P);
if (MotodooriSuuList.Count > 1) break;
}
if (MotodooriSuuList.Count == 1) {
Console.WriteLine(new string('■', 30));
Console.WriteLine("Answer={0}", Q);
break;
}
}
Console.WriteLine("経過時間={0}", sw.Elapsed);
}
//Qを引数をして、Pの上限を求める
static long DeriveLimitP(long pQ)
{
Console.WriteLine("Q={0}の場合の、検索するPの上限を求めます。", pQ);
for (long Ketasuu = 1; ; Ketasuu++) {
long wkMin = DeriveMin(Ketasuu);
long wkMax = DeriveMax(Ketasuu);
Console.WriteLine("Pが{0}桁の場合、Pの最小値={1}、Pの最大値={2}",
Ketasuu, wkMin, wkMax);
long wkKetasuu = (long)Math.Truncate(pQ * Math.Log10(wkMax)) + 1;
Console.WriteLine("{0}の{1}乗の桁数={2}で、各桁の数字の和の最大は、{2}*9で{3}",
wkMax, pQ, wkKetasuu, 9 * wkKetasuu);
if (wkMin > 9 * wkKetasuu) {
//1桁小さい数の最大値までチェックすればOK
long WillReturn = DeriveMax(Ketasuu - 1);
Console.WriteLine("Q={0}での、検証するPの上限={1}", pQ, WillReturn);
return WillReturn;
}
}
}
//指定桁での最小値を求める
static long DeriveMin(long pKetaSuu)
{
return (long)Math.Pow(10, pKetaSuu - 1);
}
//指定桁での最大値を求める
static long DeriveMax(long pKetaSuu)
{
return (long)Math.Pow(10, pKetaSuu) - 1;
}
//PのQ乗が、もとどおり数かを返す
static bool IsMotodooriSuu(long pP, long pQ)
{
if (IsMotodooriSuuHelper(pP, pQ) == false) return false;
long[] wkLongArr = new long[9999];
long CurrKeta = 1;
long CopiedP = pP;
while (CopiedP > 0) {
wkLongArr[CurrKeta++] = CopiedP % 10;
CopiedP /= 10;
}
for (int I = 1; I <= pQ - 1; I++) {
for (int J = 1; J <= wkLongArr.GetUpperBound(0); J++) {
wkLongArr[J] *= pP;
}
for (int J = 1; J <= wkLongArr.GetUpperBound(0); J++) {
if (wkLongArr[J] >= 10) {
wkLongArr[J + 1] += wkLongArr[J] / 10;
wkLongArr[J] %= 10;
}
}
}
//添字の0番目を消す
wkLongArr = wkLongArr.Skip(1).ToArray();
if (wkLongArr.Sum() == pP) {
string[] wkStrArr = Array.ConvertAll(wkLongArr, X => X.ToString());
string wkStr = string.Concat(wkStrArr);
wkStr = new string(wkStr.Reverse().ToArray());
Console.WriteLine("{0,3}の{1,2}乗={2}はもとどおり数です",
pP, pQ, wkStr.TrimStart('0'));
return true;
}
return false;
}
//PのQ乗が、もとどおり数かを返す
static bool IsMotodooriSuuHelper(long pP, long pQ)
{
//PのQ乗 = Pの各桁の和 であることの必要条件
//PのQ乗 Mod 9 = Pの各桁の和 Mod 9
//を満たすかを九去法で判定
long BekijyouMod9 = pP % 9;
for (long I = 2; I <= pQ; I++) {
BekijyouMod9 *= pP;
BekijyouMod9 %= 9;
}
return pP % 9 == BekijyouMod9;
}
}