「プロジェクトオイラー問74」の編集履歴(バックアップ)一覧はこちら

プロジェクトオイラー問74」(2014/03/02 (日) 06:00:25) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

http://projecteuler.net/problem=74 *Problem 74 「桁の階乗による連鎖」 † 145は各桁の階乗の和が145と自分自身に一致することで有名である. 1! + 4! + 5! = 1 + 24 + 120 = 145 169の性質はあまり知られていない. これは169に戻る数の中で最長の列を成す. このように他の数を経て自分自身に戻るループは3つしか存在しない. 169 → 363601 → 1454 → 169 871 → 45361 → 871 872 → 45362 → 872 どのような数からスタートしてもループに入ることが示せる. 例を見てみよう. 69 → 363600 → 1454 → 169 → 363601 (→ 1454) 78 → 45360 → 871 → 45361 (→ 871) 540 → 145 (→ 145) 69から始めた場合, 列は5つの循環しない項を持つ. また100万未満の数から始めた場合最長の循環しない項は60個であることが知られている. 100万未満の数から開始する列の中で, 60個の循環しない項を持つものはいくつあるか? 解法 7ケタが全部9でも254万程度で、8桁になっても280万程度です。 つまり多めに見積もっても260万程度までをメモ化しておけばよいと分かります。 これで十分間に合います。 #include<stdio.h> #include<string.h> char lens[2600000]; const int fact[10]={1,1,2,6,24,120,720,5040,40320,362880}; int toNextNum(int num){ int re=0; while(num!=0){ re+=fact[num%10]; num/=10; } return re; } int search(int num){ if(num==toNextNum(num)){ lens[num]=0; return 0; } if(lens[num]>=0){ return lens[num]; }else{ lens[num]=0; lens[num]=search(toNextNum(num))+1; if(lens[num]>60)lens[num]=60; return lens[num]; } } int main(){ int ans=0; memset(lens,-1,sizeof(lens)); for(int i=1;i<1000000;i++){ if(lens[i]>=0){ ans+=(lens[i]>=60); }else{ ans+=(search(i)>=60); } } printf("%d\n",ans); }
http://projecteuler.net/problem=74 *Problem 74 「桁の階乗による連鎖」 † 145は各桁の階乗の和が145と自分自身に一致することで有名である. 1! + 4! + 5! = 1 + 24 + 120 = 145 169の性質はあまり知られていない. これは169に戻る数の中で最長の列を成す. このように他の数を経て自分自身に戻るループは3つしか存在しない. 169 → 363601 → 1454 → 169 871 → 45361 → 871 872 → 45362 → 872 どのような数からスタートしてもループに入ることが示せる. 例を見てみよう. 69 → 363600 → 1454 → 169 → 363601 (→ 1454) 78 → 45360 → 871 → 45361 (→ 871) 540 → 145 (→ 145) 69から始めた場合, 列は5つの循環しない項を持つ. また100万未満の数から始めた場合最長の循環しない項は60個であることが知られている. 100万未満の数から開始する列の中で, 60個の循環しない項を持つものはいくつあるか? 解法 7ケタが全部9でも254万程度で、8桁になっても280万程度です。 つまり多めに見積もっても260万程度までをメモ化しておけばよいと分かります。 これで十分間に合います。 今回もC++でPrologではありません。 #include<stdio.h> #include<string.h> char lens[2600000]; const int fact[10]={1,1,2,6,24,120,720,5040,40320,362880}; int toNextNum(int num){ int re=0; while(num!=0){ re+=fact[num%10]; num/=10; } return re; } int search(int num){ if(num==toNextNum(num)){ lens[num]=0; return 0; } if(lens[num]>=0){ return lens[num]; }else{ lens[num]=0; lens[num]=search(toNextNum(num))+1; if(lens[num]>60)lens[num]=60; return lens[num]; } } int main(){ int ans=0; memset(lens,-1,sizeof(lens)); for(int i=1;i<1000000;i++){ if(lens[i]>=0){ ans+=(lens[i]>=60); }else{ ans+=(search(i)>=60); } } printf("%d\n",ans); }

表示オプション

横に並べて表示:
変化行の前後のみ表示: