トップページに戻る
次のC#のサンプルへ
前のC#のサンプルへ
Cマガ電脳クラブ(第110回) 欲張りな2数
問題
ここに「56097」と「14128」という5桁の数がある。
この2数の和は「70225」で、265の2乗、つまり平方数となっている。
また、差は「41969」で、素数となっている。
さらに、積は「792538416」で、なんと小町数となっているのだ。このように、
(1) A+Bが平方数になる
(2) A−Bが素数になる
(3) A×Bが小町数になる
という3つの条件を同時に満たす5桁の正の整数 A, B (ただしA>B) のペアをすべて求めていただきたい。
前述の例を含めて何通りあるだろうか。
なお、小町数とは,1〜9の数字がすべてひとつずつ登場している9桁の数のことである。
ソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
//平方数の配列を返す
int[] HeihousuuArr = DeriveHeihousuuArr();
//エラトステネスの篩で5桁の最大値以下の素数の配列を返す
int[] SosuuArr = Eratosthenes();
int AnswerCnt = 0;
//AとBのペアを列挙
for (int LoopA = 10000; LoopA <= 99999; LoopA++) {
//10の倍数なら積が小町数にならない
if (LoopA % 10 == 0) continue;
for (int LoopB = 10000; LoopB < LoopA; LoopB++) {
int Wa = LoopA + LoopB;
int Sa = LoopA - LoopB;
int Seki = LoopA * LoopB;
//小町数の最大値を超えたらBreak
if (Seki > 987654321) break;
if (Array.BinarySearch(HeihousuuArr, Wa) < 0)
continue;
if (Array.BinarySearch(SosuuArr, Sa) < 0)
continue;
if (IsKomatiSuu(Seki) == false) continue;
AnswerCnt++;
Console.WriteLine("解{0}を発見。経過時間={1}", AnswerCnt, sw.Elapsed);
Console.WriteLine("A={0},B={1},和={2},差={3},積={4}",
LoopA, LoopB, Wa, Sa, Seki);
}
}
}
//平方数の配列を返す
static int[] DeriveHeihousuuArr()
{
var WillReturn = new List<int>();
const long MinVal = 10000 + 10000;
const long MaxVal = 99999 + 99999;
//5桁+5桁の最小値から最大値までの平方数を列挙
for (int I = 0; I * I <= MaxVal; I++) {
if (I * I < MinVal) continue;
WillReturn.Add(I * I);
}
return WillReturn.ToArray();
}
//エラトステネスの篩で5桁の最大値以下の素数の配列を返す
static int[] Eratosthenes()
{
var IsSosuuArr = new System.Collections.BitArray(99999 + 1);
for (int I = 2; I <= IsSosuuArr.Count - 1; I++) {
IsSosuuArr[I] = true;
}
for (int I = 2; I * I <= IsSosuuArr.Count - 1; I++) {
if (IsSosuuArr[I] == false) continue;
for (int J = I * 2; J <= IsSosuuArr.Count - 1; J += I) {
IsSosuuArr[J] = false;
}
}
var SosuuList = new List<int>();
for (int I = 2; I <= IsSosuuArr.Count - 1; I++) {
if (IsSosuuArr[I]) SosuuList.Add(I);
}
return SosuuList.ToArray();
}
//小町数かを判定
static bool IsKomatiSuu(int pTargetNum)
{
if (pTargetNum < 123456789) return false;
if (pTargetNum > 987654321) return false;
bool[] IsAppearedArr = new bool[10];
int CopiedVal = pTargetNum;
do {
int ModVal = CopiedVal % 10;
//0を含んだらNG
if (ModVal == 0) return false;
//同じ数字を2個以上含んだらNG
if (IsAppearedArr[ModVal]) return false;
IsAppearedArr[ModVal] = true;
} while ((CopiedVal /= 10) > 0);
return true;
}
}
実行結果
省略
解66を発見。経過時間=00:01:49.0935878
A=64998,B=11731,和=76729,差=53267,積=762491538
解67を発見。経過時間=00:01:50.2010532
A=66238,B=13851,和=80089,差=52387,積=917462538
解68を発見。経過時間=00:01:51.4849158
A=67752,B=11209,和=78961,差=56543,積=759432168
解69を発見。経過時間=00:01:56.7840055
A=75546,B=11479,和=87025,差=64067,積=867192534
解70を発見。経過時間=00:01:57.6842366
A=77287,B=12114,和=89401,差=65173,積=936254718
解説
事前に平方数と素数を配列で求めておいて、バイナリサーチを使ってます。