きれいに書けないループ
ちょっとした疑問,兼 Euler 302 反省会。いろいろミスしたのだけど一番しょうもないやつ。
N > n * p^e となる e についてループしたい。どう書きましょう,というお話。
素直に書くと
for (long n1 = n * p; n1 < N; n1 *= p) { ... }
ですが,N, p が大きいと n1 *= p で溢れるに決まってます。
それでしかたがないので
double e1 = (log(N/n)) / log(p); long pp = p; for (int e = 1; e < e1; e++, pp *= p) { ... }
というふうな調子で書いてみましたが,これは正しく動作しませんでした。N = n * 243, p = 3 のときのように e1 の真の値が整数になる場合に,ループの回数が過剰だったり不足したりする可能性があります。
しょうがないのでむりやり直したバージョン。
double eps = 1e-10; double e1 = (log(N/n)) / log(p) + eps; long pp = p; for (int e = 1; e < e1; e++, pp *= p) { long n1 = n * pp; if (n1 >= N) break; ... }
今回は N = 10^18 だったので,e1 を少し大きめに見積もったせいで N を少し超えたとしても溢れないという楽観的な予想。
あまり美しくない。もっといい方法ありませんか。