Petitverse
ゲストさん (
ログイン
)
ログイン
コミュニティ内検索
コミュニティ一覧
Petitverse ご利用ガイド
Petitverse からのおしらせ
プチコン 非公式コミュニティ
プレイ日記
こういち
◆ou0jbJnEJ0Kb
2019/8/28 9:39
問題
サンタさんは、自分の副業が空き巣だということを皆に打ち明けようと思っています。
任意の人に自分の正体を打ち明けたとき、その人は1/Nの格率で絶望し、サンタさんのファンをやめてしまいます。
M人に正体を打ち明けたとき、サンタさんのファンが一人も減らない確率の逆数を32768で割った余りを求めてください。
コメント
Na
2019/8/30 19:59
◆QoELVrBXBQCI
かなり上に書いたFOR使ったコード、全然間違ってました
N/(N-1)は整数じゃないから、毎回32768を引くではだめだった
SatoshiMcCloud
2019/8/30 20:11
◆Z1qfV11i63Jr
本当に計算が省略できるか手動で計算してみましたが、小数点基準で考えると省略可能になるまで結構かかりました。この方法は失敗かもしれない…
まあ組み合わせ計算のCが出た時点である程度は察してましたが…うーん
Na
2019/8/30 20:23 ネタバレ
◆QoELVrBXBQCI
>SatoshiMcCloudさん
今試したのですがMが大きくなるとmCnの部分が大きくなりすぎて正確に計算できなくなってしまいます...
試したコード
N=20
M=1000
K=1/(N-1) 'N/(N-1)-1と同じ
A=0
FOR I=0 TO M
B=C(M,I)*POW(K,I)
IF B<0.000000001 THEN BREAK
A=A+B
A=A-FLOOR(A/32768)*32768
?I,B:VSYNC 2 '確認用
NEXT
?A
DEF C(A,B)
'階乗を使うとinfになる
IF B==1 THEN RETURN 1
RETURN C(A,B-1)*(A-B+1)/B
END
さらに試したところM=500くらいまでなら小数点以下3桁まで合います。
このコメントはネタバレを含んでいます。
このコメントをひらく
SatoshiMcCloud
2019/8/30 20:44
◆Z1qfV11i63Jr
>>Naさん
やっぱそうなりますかね…
高原のな
2019/8/30 20:58 ネタバレ
◆bY8RViwvoODw
Naさん>
動作には全く関わらないので特にどうということはないですが、実装法は再帰を使わない方が良いかと思います(主に速度面とスタックの問題)
なお、次のコードは手元にあったアルゴリズムの本のコードをSmileBASICに変換しただけのものです
DEF C(N,R)
VAR I,P=1
FOR I=1 TO R
P=P*(N-I+1)/I
NEXT
RETURN P
END
このコメントはネタバレを含んでいます。
このコメントをひらく
SatoshiMcCloud
2019/8/30 22:00
◆Z1qfV11i63Jr
がんばったけど、満足な精度が出ないのでギブアップします。無念…
高原のな
2019/8/30 22:47
◆bY8RViwvoODw
32bitよりでかい整数を配列を用いて表現しているのですが、でかい整数同士の掛け算と割り算(特に割り算)さえ実装できれば問題は解決
ユークリッドの互除法を用いて最大公約数を算出→約分という処理をどうにかうまくできれば……
高原のな
2019/8/30 22:48
◆bY8RViwvoODw
(筆算の割り算を10進法以外に拡張するとか?)
Na
2019/8/30 22:54
◆QoELVrBXBQCI
>高原のなさん
文字列を用いて表現するという方法は(適当)
高原のな
2019/8/30 23:00
◆bY8RViwvoODw
(実装してみて思ったけれど、確かに文字列の方が簡単そう)
高原のな
2019/8/31 0:19
◆bY8RViwvoODw
(あと整数の割り算さえ実装すれば、Nが有理数なら無限精度の実装が完成する)
SatoshiMcCloud
2019/8/31 0:25
◆Z1qfV11i63Jr
最終手段としては、確率問題なら実際に試行してみる手がある!
それにしたって精度が欲しいなら相当回数試行しないとダメですが…。
高原のな
2019/8/31 0:30
◆bY8RViwvoODw
(割り算処理を除いて)完成した…… 現時点で32768で割る前の分数表示までできる
割り算処理を書くの面倒なので正直やりたくないけど、やらないことには完成しない……ちゃんとそのうちやる
(追記:無限精度C#解(途中かけ)をGitHub Gistにアップしました。興味のある方はどうぞ。
https://gist.github.com/taka-impact/170e13ed867431b478f5d599d1eac76b
)
(追記2:LargeIntegerクラスですが、同符号の場合絶対値の大小になってしまうという実装ミスをしました。もし利用される際はお気をつけて)
こういち
2019/9/24 15:19
◆ou0jbJnEJ0Kb
盛り上がってますね。
逆元が、互いに素でないと存在しないという事実を知って絶望中。
やっぱり気合いで巨大な数の計算できるようにするしかないのかな…
そもそも分数を32768で割った余りって何やねん。
これ、最後の1文を
M人に正体を打ち明けたとき、M人全員がサンタさんのファンをやめる確率の逆数を20123で割った余りを求めてください。
に変えたら大分解きやすくなるんだろうな…(夢の中が元ネタなので問題文ガハガバ)
高原のな
2019/9/24 20:27
◆bY8RViwvoODw
そういえば割り算をまだ作ってないのだ〜〜〜()
実装は小学校で習った筆算のやり方でできそうですね.ただ重そうですが
一応プチコンにも移植できそうなので,割り算ができ次第やってみようと思いました
こういち
2019/10/15 8:37 ネタバレ
◆ou0jbJnEJ0Kb
変更後の問題の想定解
VAR N%,M%,ANS%=1
INPUT N%,M%
WHILE M%
IF M% AND 1 THEN ANS%=ANS%*N% MOD 20123
N%=N%*N% MOD 20123
M%=M%>>1
WEND
PRINT FORMAT$("%d",ANS%)
このコメントはネタバレを含んでいます。
このコメントをひらく
こういち
2019/10/21 16:24
◆ou0jbJnEJ0Kb
>そもそも分数を32768で割った余りって何やねん。<
https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a
逆元ついて調べてみたら、ここに記述がありました。
a/bをpで割ったときの余りは、pで割ったときのbの逆元にaを掛けたものだそうです。
こういち
2019/10/21 22:42
◆ou0jbJnEJ0Kb
今まで当たり前のように逆元と呼んでたそれ。モジュラ逆数という名前がついていたようです。
蟻本の影響力なのか…
こういち
2019/10/21 23:09
◆ou0jbJnEJ0Kb
ちなみに、bと32768が互いに素というのはbが奇数であると言い換えることができる。多分。
こういち
2019/11/11 14:29
◆ou0jbJnEJ0Kb
恐らく解けました。長かった。
とりあえずC言語で書いてみた。
あとはプチコンで書き直せば完成なはず。
1
2
3
コメントを書く
こちらは「プチコン3号」「プチコンBIG」など、
プチコンシリーズ
に関する話題を扱った
コミュニティです
プチコンシリーズにまったく関係ない書き込みはご遠慮下さい。削除の対象となります
こちらにはその他のゲームや雑談のコミュニティはなく、作る予定もありません (ひとりで管理できないため)。ごめんなさい
ユーザー登録なしで書き込みができます
秘密の合い言葉は成りすましの防止 (
トリップ機能
)、書き込みの編集時の本人認証に使用します
秘密の合い言葉に他人に推測されやすい言葉、他サービスと同じパスワードは入力しないでください。
書き込むと、投稿時に入力したお名前と秘密の暗号が記憶され、ログイン状態になります
normal
happy
like
surprized
frustrated
puzzled
画像
ネタバレ
投稿する
-
WEB PATIO
-