ひさびさのEuler充

週末に20問くらい解いた。

フォーラム見てたら、数列の階差を取ってみると1個とばしのフィボナッチ数列で一個おきに2倍になってるよ (F[3], 2F[5], F[7], 2F[9], ...) とか普通に気づく人がいたりして笑った。変態すぎるぜ。

今まで問題の手のつけ方が汚くてプロフィールページの見た目があまりにもアレだったので、ちまちまと食べ残しの穴を片付けてます。だいぶマシになったかしら。きちんと順番に解いてる人えらいー。

以下ここ数日の回想(ネタバレ)

60

素数をノードとするグラフ作ってサイズ5のクリークを求める。
次数の低い、数字の大きな方からチェックすると速い。
そして遅延評価をうまくつかった brute force かっこいい。そんな素直にいけちゃうのかー。

84

遷移確率の行列作るだけ。めんどかった。

100

このあたりで一般的な二次曲線上の整数点の列挙の方法を学ぶ。

101

連立一次方程式をつくって解く。行列ライブラリ便利ー。

103, 105, 106 (Special Sum Set)

大きい要素k個よりも、小さい要素(k+1)個のほうがでかくなればいい。サブセット間で和が等しくならないかチェックは重いので後回し。

103は、なんかヒントがそのまま答えだった。周りを探索しても何も見つからなくてあれ?と思った。

106は (∀i. B[i] < C[i]) => S(B) < S(C) を使うだけ。

110

x = n+k, y = n(n+k)/k (x ≦ y) を考える。k は n^2 の約数のうち n 以下のもの。

n = (2^a)(3^b)(5^c)... のとき n^2 の約数の個数は (2a+1)(2b+1)(2c+1)... で、そのうち半分が n 未満かつ n は約数になる。
結局条件 (2a+1)(2b+1)(2c+1)... > M を満たしつつ n = (2^a)(3^b)(5^c)... を最小化する話になる。

111

"repeated" って 1151みたいに連続してなくても良いんか?っておもった。愚直にやると計算量が怖かったけど、実際やってみるとそうでもなかった。

126
  • 面を抑えるのに必要な個数は定数
  • 辺を抑えるのに必要な個数は線形に増える
  • 頂点を抑えるのに必要な個数は二次関数

と分けて考える。

127

rad は予め全部計算して配列に入れとく。

gcd(b,a) == 1 && rad[a]*rad[b] < q

rad[a]*rad[b] < q && gcd(b,a) == 1

にしたら 1m40s → 6s になった。意味的には前者の方が気持ち良いんだけど…。

129, 132, 133 (Repunit)

1 を 9n で割って循環小数に展開していくと、途中で1余る状態が出てくる。このとき 1000..0 ≡ 1 mod 9n 、つまり 9n = 999..9

135, 136 (x^2 - y^2 - z^2)

(y+k)^2 - y^2 -(y-k)^2 を brute force

137, 140 (Golden nuggets)

母関数を出す → xについて解く → 判別式が平方数
で、 (Aの二次式) = k^2 を満たす整数を列挙。

140が若干きつくて、Aをp,qの分数式で表した後、p,q をどうなめればいいのか分からなかった。
数列を観察してみると、なんか(p^2 - 5q^2) が 1,4,11,44 のどれかにしかならないっぽかったからそれを仮定して答えを出したらあってた。なんつうアドホック天国。