トップページに戻る
次のC#のサンプルへ
前のC#のサンプルへ
Problem170 連結された積が0から9を網羅する数の最大値
問題
6を1273と9854に掛けると,
6 × 1273 = 7638
6 × 9854 = 59124
となる.
これらの積をつなげることで, 1から9を網羅するパンデジタル数, 763859124を得る.
763859124を"6と(1273,9854)の連結された積"と呼ぶことにする.
元の数をつなげた 612739854も1から9を網羅する数であることに注意.
同じことが0から9を網羅する数にたいしてもできる.
元の数をつなげた数も0から9を網羅する数となるような,
ある整数と2つ以上の整数の連結された積が0から9を網羅する数の最大値を求めよ.
ソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
const int UB = 9;
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
string AnswerStr = new string('0', 10);
foreach (string EachKouho in DeriveKouhoEnum()) {
//Aは2桁まで
for (int I = 0; I <= 1; I++) {
string AStr = EachKouho.Substring(0, I + 1);
int AInt = int.Parse(AStr);
List<long> NumListA = DeriveNumList(AInt);
//Mod9で枝切り
long ModVal = AInt % 9;
ModVal *= 2; //Aは2回使う
for (long J = 0; J <= 9; J++) {
if (NumListA.Contains(J) == false)
ModVal += J % 9;
}
if (ModVal % 9 > 0) continue;
for (int J = I + 1; J <= UB - 1; J++) {
string BStr = EachKouho.Substring(I + 1, J - I);
string CStr = EachKouho.Substring(J + 1);
//前ゼロは不許可
if (BStr.Length > 1 && BStr.StartsWith("0")) continue;
if (CStr.Length > 1 && CStr.StartsWith("0")) continue;
int BInt = int.Parse(BStr);
int CInt = int.Parse(CStr);
long DLong = (long)AInt * BInt;
long ELong = (long)AInt * CInt;
List<long> wkNumList = new List<long>();
wkNumList.AddRange(DeriveNumList(DLong));
wkNumList.AddRange(DeriveNumList(ELong));
if (wkNumList.Count != 10) continue;
if (wkNumList.GroupBy(X => X).Any(X => X.Count() > 1)) continue;
string CurrStr = string.Format("{0}{1}", DLong, ELong);
if (AnswerStr.CompareTo(CurrStr) < 0) {
AnswerStr = CurrStr;
Console.WriteLine("解候補を発見");
Console.WriteLine("{0}*{1}={2}", AInt, BInt, DLong);
Console.WriteLine("{0}*{1}={2}", AInt, CInt, ELong);
Console.WriteLine("連結積は{0}", CurrStr);
Console.WriteLine();
}
}
}
}
Console.WriteLine("経過時間={0}", sw.Elapsed);
}
struct JyoutaiDef
{
internal string CurrStr;
}
//同じ数字を複数含まない10桁の数の列挙を返す
static IEnumerable<string> DeriveKouhoEnum()
{
var KouhoList = new List<string>();
var Stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
for (char I = '1'; I <= '9'; I++) {
WillPush.CurrStr = I.ToString();
Stk.Push(WillPush);
}
while (Stk.Count > 0) {
JyoutaiDef Popped = Stk.Pop();
//クリア判定
if (Popped.CurrStr.Length == 10) {
yield return Popped.CurrStr;
continue;
}
for (char I = '0'; I <= '9'; I++) {
if (Popped.CurrStr.Contains(I))
continue;
WillPush.CurrStr = Popped.CurrStr + I.ToString();
Stk.Push(WillPush);
}
}
}
//数字のListを返す
static List<long> DeriveNumList(long pTarget)
{
var WillReturn = new List<long>();
long CopiedVal = pTarget;
do {
long ModVal = CopiedVal % 10;
WillReturn.Add(ModVal);
CopiedVal /= 10;
} while (CopiedVal > 0);
return WillReturn;
}
}
実行結果
解候補を発見
9*87345=786105
9*1026=9234
連結積は7861059234
解候補を発見
9*1=9
9*87345026=786105234
連結積は9786105234
解候補を発見
27*36508=985716
27*149=4023
連結積は9857164023
経過時間=00:00:15.7157397
解説
A*B=D
A*C=E
とすると、
Aが5桁の場合、5*3=15で10桁を超えるので不適
Aが4桁の場合、4*3=12で10桁を超えるので不適
Aが3桁で、Bが1桁でCが1桁の場合、3+3+3=9
Aが3桁で、Bが1桁でCが2桁の場合、3+3+4=10
Aが3桁で、Bが1桁でCが3桁の場合、3+3+5=11
Aが3桁で、Bが2桁でCが2桁の場合、3+4+4=11
以上により、Aが3桁の場合も不適ですので、Aは2桁以下となります。
また、
A*BにA*Cを連結したものがパンデジタル数(9の倍数)なので
A*B + (10のA*Bの桁数乗)*A*C が9の倍数となります。
なので、(A*B+A*C)%9 == 0 を必要条件として使ってます。