プログラムの実行結果は以下の通り。
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; }