Upload
okuraofvegetable
View
215
Download
2
Embed Size (px)
DESCRIPTION
NPC April Fool's Contest Wrapping potato chips is fun
Citation preview
楽しいポテトチップスの袋詰め (Wrapping potato chips is fun) 解説
@okuraofvegetabl
問題概要 2つの自然数 N,K が与えられる。
1≦N,K≦3*10^6
1≦A1<A2…Ak-1<Ak≦N
A(奇数)=奇数、A(偶数)=偶数
を満たす数列Aの数(mod 10^9+7)を求めたい。
ぽてち先生は韓国に行っている。
考察(1) 自明な場合
- KがNより大きいとき、条件を満たす数列が
存在しないのは明らか
- 逆に、NがK以上のとき、条件を満たす数列が
少なくとも一つ存在する
(A1=1,A2=2…,AK=K)
考察(2)
N,Kがそれぞれn,kのときのmodをとる前の解を
f(n,k)と表すことにする。
nとkの偶奇が異なるとき、
- Akの偶奇はkと同じでn以下なのでnは使われない
- f(n,k)=f(n-1,k)
- したがってn,kの偶奇が一致する場合のみ考えればよい
考察(2) N=Kのとき
- 解は (A1=1,A2=2…,AK=K) の1通りのみ。
- ゆえにf(n,k)=1
- 先程の考察を考慮すると、N=K+1のときも
- f(n,k)=1
考察(3)
今後は、n,kの偶奇は一致しているとします。
f(n,k)をA1が1の時とそうでない時に分けて考えてみると…
A1が1のとき 2以上n以下の整数からA2,A3…Akを条件を満たすように選ぶ方法の数
- この問題は1以上n-1以下の整数からA1A2…Ak-1を
条件を満たすように選ぶ問題に帰着できる。
- したがってf(n-1,k-1)に等しい
A1が1でないとき 3以上n以下の整数からA1,A2…Akを条件を満たすように選ぶ方法の数
- A1は奇数なので少なくとも3以上だから
- この問題は1以上n-2以下の整数からA1A2…Akを
条件を満たすように選ぶ問題に帰着できる。
-したがってf(n-2,k)に等しい
考察(4) 以上より、
f(n,k)=f(n-1,k-1)+f(n-2,k) (n≧3)
ん?、これは漸化式…
DPだ!!
え、でもちょっと待てよ、
1≦N,K≦3*10^6
(絶望)
とりあえず埋めてみる K\N 1 2 3 4 5 6 7
1 1 1 2 2 3 3 4
2 × 1 1 3 3 6 6
3 × × 1 1 4 4 10
4 × × × 1 1 5 5
とりあえず埋めてみる K\N 1 2 3 4 5 6 7
1 1 1 2 2 3 3 4
2 × 1 1 3 3 6 6
3 × × 1 1 4 4 10
4 × × × 1 1 5 5
とりあえず埋めてみる K\N 1 2 3 4 5 6 7
1 1 1 2 2 3 3 4
2 × 1 1 3 3 6 6
3 × × 1 1 4 4 10
4 × × × 1 1 5 5
勘のいい方ならもうお気づきかもしれませんが…
パスカルの三角形っぽい
パスカルの三角形
パスカルの三角形
考察(5) 出てくる数字がパスカルの三角形にもある
-> nCrの形で表せるのでは?
- 実際、あの表を手で書いてみて
パスカルの三角形との対応を考えると
f(n,k) = (n+k)/2Ck だとわかる。
証明(1) 実は、今までの漸化式などは全く考える必要がなかった。
まず、A0=0、Ak+1=n+1とする。
ここで、階差数列 Bi = Ai+1-Ai (0≦i≦k) を考える。
任意のBiは奇数で、定義より、
B0+B1+…+Bk = Ak+1 - A0 = n+1 である。
Ci=(Bi – 1)/2 (0≦i≦k)とおくと、
C0+C1+…+Ck = {(n+1)-(k+1)}/2 = (n-k)/2
証明(2) 各Ciには非負整数を好きな順で入れられるので、
f(n,k)は、総和が(n-k)/2となる要素数がk+1個の
非負整数列(重複可)の数と一致する。
この場合の数は(n-k)/2個の○と
(k+1)-1=k個の|を並べる場合の数に対応する。
ゆえに f(n,k) = {(n-k)/2+k} Ck = (n+k)/2 Ck
nCr = n!/(n-r)!/r!
これであとは普通に計算するだけですが、
注意すべきことが一つだけあります。
(ある程度問題を解いている方にはあたりまえだろ、
といわれてしまいそうですが…)
MODがらみの計算 ある値のmod hoge を出力せよという問題は多々あります。
hogeが素数の時(本問)、足し算、引き算、掛け算は
普通に計算して逐一modをとれば問題ありません。
では割り算をしたいときはどうすればいいのでしょうか…
MODで割り算 MODのからむ計算で、xで割り算をしたいときは、
1/xと等価な数(逆元,x^-1)を掛けてやることで、
正しく値を求めることができます。
本問ではmod 素数なので、
フェルマーの小定理よりx^(p-1)≡1(mod p)
で、xの逆元はx^(p-2)(mod p)となります。
逆元 しかし本問では、n回も割り算をしないといけないので、
累乗に繰り返し2乗法を用いても間に合わないかも
知れません。
実は、xの逆元は1…x-1の逆元から簡単に求めることができて、1からxまでの逆元はO(x)で列挙することができます。
xの逆元をinv[x]で表すと、
inv[x]=MOD-(MOD/x)*inv[MOD%x]%MOD
計算量 1から(N+K)/2までの逆元の列挙でO(N+K)
{(N+K)/2}!と{(N-K)/2}!、K!の逆元を求めるのにO(N+K)
あわせてO(N+K)
Submit数 18
AC数 9
FA IH19980412(HIR180) (1:23)