c21coterie @ ウィキ
http://w.atwiki.jp/c21coterie/
c21coterie @ ウィキ
ja
2014-03-09T08:24:05+09:00
1394321045
-
プロジェクトオイラー問130
https://w.atwiki.jp/c21coterie/pages/954.html
*Problem 130 「素数桁レピュニットと同じ性質を持つ合成数」 †
1からのみなる数をレピュニットと呼ぶ. R(k)で長さkのレピュニットを表す. 例えばR(6) = 111111である.
GCD(n, 10) = 1 となる正整数 n について, 必ず正整数 k が存在し n が R(k) を割り切ることが証明できる. A(n) でそのような最小の k を表す. 例: A(7) = 6. A(41) = 5.
5より大きい素数 p について, A(p) が p - 1 を割り切ることが知られている. p = 41 のときには, A(41) = 5 であり, 40は5で割り切れる.
非常に少ないのだが, 合成数においても上が成立する場合がある. 最初の5つの例は 91, 259, 451, 481, 703 である.
GCD(n, 10) = 1 かつ A(n) が n - 1 を割り切るような最初の25個の合成数 n の総和を求めよ.
解法
1111、、、1111の9倍は
(10^t)-1=999,,,999と表現できます。
(10^t) mod N*9=1
となれば
((10^t)-1)/9=111,,,111はnで割り切れます。
tはオイラーの定理よりφ(n)となります。
not_prime(N):-N<2,!.
not_prime(N):-
between(2,N,D),
(D*D>N->!,fail;true),
N mod D=:=0,
!.
is_prime(N):-not(not_prime(N)).
divs(N,Div,N):-N mod Div>0,!.
divs(N,Div,Result):-
!,
N1 is N//Div,
divs(N1,Div,Result).
fai(1,_,Result,Result):-!.
fai(N,Div,Re,Result):-
N<Div*Div,
!,
Result is (Re/N)*(N-1).
fai(N,Div,Mult,Result):-
N mod Div=:=0,
!,
divs(N,Div,
2014-03-09T08:24:05+09:00
1394321045
-
プロジェクトオイラー問129
https://w.atwiki.jp/c21coterie/pages/953.html
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%20129
*Problem 129 「レピュニットの非整除性」 †
1のみからなる数をレピュニットという. R(k) を長さ k のレピュニットとする. 例えば, R(6) = 111111 となる.
GCD(n, 10) = 1 なる正の整数 n が与えられたとき, R(k) が n で割り切られるような k が常に存在することが示せる. A(n) をそのような k の最小のものとする. 例えば, A(7) = 6, A(41) = 5 となる.
A(n) の値が10を超える最小の n は17である.
A(n) の値が100万を超える最小の n を求めよ
解法
111、、、111を9倍すると999、、、9999.
10^t-1=999、、、999
オイラーの定理より
10^φ(n) mod n=1
φ(n)の約数が候補になる。
nで割れる最小の長さの111、、111を9倍しても一桁大きい111、、111を超えない。
そして100万を超えた最初の素数nはφ(n)の約数はn-1のみでいきなり100万以上を満たす。
よって100万より大きい最初の素数が答え。
2014-03-09T06:20:54+09:00
1394313654
-
プロジェクトオイラー問126
https://w.atwiki.jp/c21coterie/pages/952.html
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%20126
*Problem 126 「直方体層」 †
3 x 2 x 1 の直方体の表面全てを覆いつくすのに必要最小限の立方体の数は 22 個である.
p_126.gif
さらにこの立体に表面を覆いつくすように2層目を追加すると, 46 個の立方体が必要である. 3層目は 78 個, 4層目は 118 個の立方体が表面を覆いつくすのに必要である.
ところで 5 x 1 x 1 の直方体への1層目も 22 個の立方体が必要である. 同様に 5 x 3 x 1, 7 x 2 x 1, 11 x 1 x 1 の直方体への1層目も全て 46 個の立方体である.
何層目かが n 個の立方体からなる直方体の数を, C(n) と定義する. C(22) = 2, C(46) = 4, C(78) = 5, C(118) = 8 となる.
154 は C(n) = 10 を満たす最小の n であることがわかる.
C(n)=1000 を満たす最小の n を求めよ.
図などの詳細はリンク先参照のこと。
解法
直方体と層を小さいほうから生成していくだけです。
イカの輪切りの要領で平面で輪切りにして考えると各層のブロック数を簡単に計算できます。
計算に1.3秒、優先順位付きキューに30万個くらい要素が入ってるのでもうちょっと賢い方法はありそうです。
#include<stdio.h>
#include<queue>
#include <time.h>
struct E{
int h,w,d,size,count,p;
bool operator<(const E& e)const{
return count>e.count;
}
void calc_count(){
int body=h*w*2+((size-1)*2+d)*h*2;
int head1=d*w*2;
int head2=(w+d)*(size-1)*2*2;
int head3=((size-1)*(size-2))/2*4*2;
2014-03-09T04:10:33+09:00
1394305833
-
プロジェクトオイラー問125
https://w.atwiki.jp/c21coterie/pages/951.html
*Problem 125 「回文数の和」 †
回文数 595 は連続する平方数の和で表すことができるという面白い性質を持つ: 6^2+7^2+8^2+9^2+10^2+11^2+12^2
1000 未満で連続する平方数の和で表せる回文数はちょうど 11 あり, その合計は 4164 である. 正の整数の平方のみをこの問題では扱うため, 1=0^2+1^2 は含めないことに注意せよ.
回文数でありかつ連続する平方数の和で表せる, 10^8 未満のすべての数の合計を求めよ.
解法
とりあえず地道に計算しても求まります。
たぶんこの問題双曲線上の整数解を求めるもっと高度な解法がありそうです。
is_palindromic(N):-
N>0,
number_codes(N,Codes),
reverse(Codes,Codes).
search2(Sum,_,_):-Sum>=10^8,!,fail.
search2(Sum,_,Sum):-
is_palindromic(Sum).
search2(Sum,N,Result):-
!,
Sum1 is Sum+N*N,
N1 is N+1,
search2(Sum1,N1,Result).
search(Result):-
between(1,8000,N),
N2 is N+2,
N22 is N^2+(N+1)^2,
search2(N22,N2,Result).
sum([],0):-!.
sum([X|Xs],Result):-
!,
sum(Xs,Re),
Result is Re+X.
main125:-
findall(N,search(N),List),
sort(List,List1),
sum(List1,Ans),
write(Ans).
2014-03-09T02:11:52+09:00
1394298712
-
プロジェクトオイラー問124
https://w.atwiki.jp/c21coterie/pages/950.html
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%20124
http://projecteuler.net/problem=124
*Problem 124 「順序付き根基」 †
n の"根基"(radical)は, rad(n) に関する問題。
詳細はリンク先参照のこと。
解法
エラトステネスの篩もどきでテーブル化して計算しソートし1万個めを求めるだけです。
計算量BigO(366401)+10万個の要素のソート。
まあ普通です。
世の中J言語使いこなしてる人多いなと思います。
J言語だとこの問題1行、究極のショートコードですね。
#include<stdio.h>
#include<algorithm>
struct E{
int n,rad;
bool operator<(const E& e)const{
if(rad!=e.rad)return rad<e.rad;
return n<e.n;
}
};
const int LIMIT=100000;
int main(){
E rads[LIMIT+1];
int bigO=0;
for(int i=0;i<=LIMIT;i++){
rads[i].n=i;
rads[i].rad=1;
bigO++;
}
for(int i=2;i<=LIMIT;i++){
if(rads[i].rad>1)continue;
for(int j=i;j<=LIMIT;j+=i){
bigO++;
rads[j].rad*=i;
}
}
std::sort(rads,rads+LIMIT+1);
printf("ans=%d BigO=%d\n",rads[10000].n,bigO);
}
2014-03-09T01:55:59+09:00
1394297759
-
飛ぶ鳥、鳥とる人,鳥とともに鳥籠をもちて鳥の歌を歌う
https://w.atwiki.jp/c21coterie/pages/949.html
飛ぶ鳥、鳥とる人鳥とともに鳥籠もちて鳥の歌を歌った
それは当たり前のふしぎな話。
鳥の歌は世界を包む。
広がるもの、広がりを持たぬ者。
思惟するもの思惟しないもの。
鳥が歌えば世界が目覚める。
石が静かに調子を合わせ、川がせせらぎをかなで、森が風と共にざわめき歌う。
鳥とともに人が歌えば世界が変わる。
自然の中へ森の中ですべてが私を包む。
タオとともに私は歩む。
鳥の歌を傍らに。
作者
堀江伸一
----
その1.5
人をゲームをするマシーンに仕立てあげただと
人を、人々をゲームを遊ぶマシーンに仕立てあげたのだよ我々は。
課金、ガチャ、ネトゲ廃人。
我らがやってきたことはそういうことだ。
君もすぐに気持ちよくなるよ。
大丈夫。
何も痛くない。
さあ。
----
その2ゴミ箱域の文章
冷えたスープ。
冷めたステーキ。
ナイフを通しフォークでとりパサポソしたそれを食べる。
状況を説明しよう。
私は今油絵で描かれた洋館の中に閉じ込められている。
世界がべた塗りなことからそれがわかった。
意識が遠のき最初に気が付いたのは入口玄関から広がる広間に奥の大階段。
室内に入り込んでる光がべったりと壁に張り付いていて、触ると光自体が少しべとべとしている。
壁も扉もシャンデリアもすべてが厚塗りに色がぼやけて重なっている。
敵の気配はしない。
確かに私はさっきまで敵と戦ってたのだ。
状況はわからないがこの洋館は油絵で作られているらしい。
私は洋館の中を探索してみる。
押しても扉は開かず窓は鋼鉄よりも固い、窓は壁そのものだ。
広間、階段、開かない扉、半開きの扉から見える寝室。
そして食堂。
洋館から出る道は見つからない。
食堂ではたき火がぬるぬると燃え木漏れ日がテーブルの上でゆらゆら揺れて午後の陽ざしが差し込みテーブルの上で光と影のダンスを踊っている。
そこにはスープ、ステーキ、サラダにパン一揃いそろっていた。
私のために用意されているのだろうか。
おなかが減っていることを思い出した。
森の中での隠密戦。
2014-03-08T22:52:04+09:00
1394286724
-
プロジェクトオイラー問123
https://w.atwiki.jp/c21coterie/pages/948.html
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%20123
*Problem 123 「素数の自乗で割った余り」 †
pn を n 番目の素数とする. (p1 = 2, p2 = 3, ...) r を (pn - 1)n + (pn + 1)n を pn^2 で割った余りとする.
例えば, n = 3 のとき, p3 = 5 であり, 4^3 + 6^3 = 280 ≡ 5 mod 25.
余り r が 10^9 より大きくなる n の最小値は 7037 である.
余り r が 10^10 より大きくなる最初の n を求めよ.
解法
愚直に小さいほうから試す以外思いつきません。
何か賢い解法でもあるものでしょうか?
not_prime(N):-
between(2,N,D),
(D*D>N->!,fail;true),
N mod D=:=0,
!.
is_prime(N):-not(not_prime(N)).
search(N,No):-
is_prime(N),
!,
No1 is No+1,
N1 is N+1,
(No1 mod 2=:=0->M is 2;M is 2*N*No1),
(M>10^10->!,write(No1);search(N1,No1)).
search(N,No):-
!,
N1 is N+1,
search(N1,No).
main123:-
search(2,0).
2014-03-09T00:43:59+09:00
1394293439
-
プロジェクトオイラー問121
https://w.atwiki.jp/c21coterie/pages/947.html
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%20121
Problem 121 「円盤ゲームの賞金額」 †
袋の中に赤い円盤 1 枚と青い円盤 1 枚が入っている. ある賭けゲームにおいて, プレイヤーは円盤を 1 枚ランダムに取り出しその色を記録する. 各ターンの終わりに円盤は袋に戻され, 追加の赤い円盤 1 枚が袋に足され, そして次の円盤がランダムに取り出される.
プレイヤーはゲームをプレイするのに 1 ポンドを支払い, ゲーム終了時に青い円盤を赤い円盤より多く取り出していれば勝利する.
ゲームが 4 ターンプレイされたとすると, プレイヤーが勝利する確率はちょうど 11/120 となる. したがって, 胴元が赤字の見込みになるまでにこのゲームで勝ちに対して割り当てるべき賞金の最大は 10 ポンドとなるであろう. 支払いはすべてポンドの整数倍であり, またゲームをプレイするのに支払われたもともとの 1 ポンドを含んでいるため, 与えられた例では実際にはプレイヤーは 9 ポンドを獲得することに注意しよう.
15 ターンがプレイされるゲーム 1 回に割り当てられるべき賞金の最大を求めよ.
解法
地道に計算するだけです。
厳密にやるなら分数計算ですが手抜きして浮動小数点でも十分まにあいます。
計算量はBigO(15*15)
型システムと相性が悪いPrologに分数型を導入するのはあまり考えられませんね。
マジックナンバーがあるので少し手癖の悪いコードとなりました。
calc_next(Number,[P1,_],[P3]):-
!,
P3 is P1/Number.
calc_next(Number,[P1,P2|Rest],[P3|Result]):-
!,
P3 is P1/Number+P2*(Number-1)/Number,
calc_next(Number,[P2|Rest],Result).
sum([],0,8):-!.
sum([X|Xs],ResultSum,ResultC):-
!,
sum(Xs,ReSum,ReC),
(0<R
2014-03-08T06:37:56+09:00
1394228276
-
プロジェクトオイラー問120
https://w.atwiki.jp/c21coterie/pages/946.html
Problem 120 「自乗で割った余り」 †
(a-1)^n+(a+1)^n を a^2 で割った余りを r と定義する.
例えば, a=7, n=3 の時, r=42 である: 6^3 + 8^3 = 728 ≡ 42 mod 49. n が変われば r も変わるが, a=7 の時 r の最大値 rmax は 42 であることがわかる.
3 ≤ a ≤ 1000 において, Σ rmax を求めよ.
解法
n乗を展開してa^2で割ると残るのはnが奇数なら末尾のan+1とan-1
偶数なら1+1だけです。
奇数の時だけ考えて
an+1とan-1を足すと2anとなります
nは奇数なのでnが増加すると
2a,6a,10a,,,と増加します。
a^2-2を4で割った余りが1か3なら2anはa(a-1)を作れます。
そうでないなら2anはa(a-2)を作れます。
後はこの場合わけを実装するだけです。
この解放は海外のプロジェクトオイラー解説サイトの方法を参考に少し処理を改善して記述しました。
type(N,N1):-R is (N-2) mod 4,member(R,[1,3]),!,N1 is N-1.
type(N,N1):-!,N1 is N-2.
search(1001,Ans):-!,write(Ans).
search(N,Ans):-
!,
type(N,N1),
Add is N*N1,
Ans1 is Ans+Add,
N11 is N+1,
search(N11,Ans1).
main120:-
search(3,0).
2014-03-08T05:12:28+09:00
1394223148
-
プロジェクトオイラー問100
https://w.atwiki.jp/c21coterie/pages/945.html
Problem 100 「組み合わせの確率」 †
箱の中に15個の青い円盤と6個の赤い円盤からなる21個の色のついた円盤が入っていて, 無作為に2つ取り出すとき, 青い円盤2つを取り出す確率P(BB)は
P(BB) = (15/21) × (14/20) = 1/2
であることがわかる.
無作為に2つ取り出すとき, 青い円盤2つを取り出す確率がちょうど1/2となるような次の組み合わせは, 箱が85個の青い円盤と35個の赤い円盤からなるときである.
箱の中の円盤の合計が1012 = 1,000,000,000,000を超えるような最初の組み合わせを考える. 箱の中の青い円盤の数を求めよ.
解法
なんとなく直感的に、行列演算で次に大きな数が出てくるのでは?
と考えて。
[[a,b],[c,d]][3,1]+[e,f]=[15,6]
[[a,b],[c,d]][15,6]+[e,f]=[85,35]
本当はもう一つ式が必要だけどこれで条件を満たすa,b,c,d,e,fを適当に試してみたらなんか解けました。
解き方が欠片も理屈だってないので何か情けない気分。
calc(B,R):-B+R>10^12,
!,
write([b,B,r,R]).
calc(B,R):-
B1 is B*5+2*R-2,
R1 is B*2+R*1-1,
write([B1,R1]),nl,
calc(B1,R1).
main100:-
calc(3,1).
2014-03-07T19:54:07+09:00
1394189647