プログラムの実行結果は以下の通り。
2006 x 33032037 = 66262266222 2006 × 33032037 ---------------------- 14042 6018 4012 6018 6018 6018 ---------------------- 66262266222
プログラムのソースは以下の通り。
#include "puzutl.h"
void psi( int i) { // 数字を1件表示する
if( i< 0 || i > 11) i = 12;
cstring s = "0123456789 ×?"; // 0〜9まではそのまま表示,10は空白,11が×
ps( "%-.2s", s+i*2);
}
void psa( int exp[], int w) { // 数字をw桁表示する
for( int i=w-1; i >= 0; i--) psi( exp[i]);
ps( "\n");
}
void ps11() { // 11桁の区切り記号のつもり
for( int i=0; i< 11; i++) {
ps( "--");
}
ps( "\n");
}
void expand( int exp[], int w, int64 val) { // 桁数を指定して1桁ずつ分解する。
int n = 0;
while( val) {
if( n >= w) return;
exp[n++] = val % 10; // 下の桁から1桁ずつ求める
val /= 10;
}
while( n < w) { // 数が足りないときは空白(10)で埋める
exp[n++] = 10;
}
}
void checkans( int m, int64 R) // 掛ける数と結果候補値
{
int64 x = R;
while( x) { // 結果が2と6だけか?
if( !((x%10) == 2 || (x%10) == 6)) return; // 2と6以外が含まれる
x /= 10;
}
ps( "2006 x %d = %I64d\n", m, R); // 結果候補として印刷する
int n = 0; // 掛ける数の桁数
int d[128]; // 掛ける数を一桁ずつ求める
for( x=m; x; x/=10) {
d[n++] = x%10;
}
if( !(d[2] == 0 && d[5] == 0)) return; // 式を見ると3桁目と6桁目は0になるはず(実際はこれが無くても答えが1つ)
int exp[100];
expand( exp, 11, 2006); psa( exp, 11);
expand( exp, 11, m); exp[10] = 11/*×*/; psa( exp, 11);
ps11();
for( int j=0; j< n; j++) { // 2006 x 1桁ずつの掛け算
if( d[j]) {
expand( exp, 11-j, 2006 * d[j]); psa( exp, 11-j);
}
}
ps11();
expand( exp, 11, R); psa( exp, 11);
}
int main( int argc, cstring argv[])
{
#if 0
// めちゃくちゃ時間が掛かる方法
int i, j;
int64 r;
ProcTime pt; pt.start();
for( i=20000000; i< 100000000; i++) {
YesNo ynNG = NO;
for( int j=i; j; j/=10) if( (j%10) == 1) { ynNG = YES; break;} // 掛ける数に1を含んでいたらダメ
if( ynNG) continue;
r = (int64)2006 * i;
checkans( i, r);
}
pt.end();
ps( "%g 秒\n", pt.sec());
#else
// 直ぐに結果が表示される方法
int no[] = { 2, 6}; // 結果は2と6だけ
for( int a=0; a< 2; a++) {
for( int b=0; b< 2; b++) {
for( int c=0; c< 2; c++) {
for( int d=0; d< 2; d++) {
for( int e=0; e< 2; e++) {
for( int f=0; f< 2; f++) {
for( int g=0; g< 2; g++) {
for( int h=0; h< 2; h++) {
for( int i=0; i< 2; i++) {
for( int j=0; j< 2; j++) {
for( int k=0; k< 2; k++) {
int64 R = no[k]+10*(no[j]+10*(no[i]+10*(no[h]+10*(no[g]+10*(no[f]+10*(no[e]+10*(no[d]+10*(no[c]+10*(no[b]+10*(no[a]*(int64)1))))))))));
if( (R % 2006) == 0) {
int m = R/2006;
YesNo ynNG = NO;
for( int j=m; j; j/=10) if( (j%10) == 1) { ynNG = YES; break;} // 掛ける数に1を含んでいたらダメ
if( ynNG) continue;
checkans( m, R);
}
}
}
}
}
}
}
}
}
}
}
}
#endif
return 0;
}