\(説明\)
ちょうど大学牡牛座のために、彼が直面した最初の質問は、実際の状況に応じて右のコースを適用する方法でした。
コースは、そこが選択することが可能で\(2N \)での祭りのカリキュラム\(N \)最後の時間を。で\(I(1≤i≤n)\)コースの期間にわたって同一のコンテンツを同時に事前牛肉教室内に配置された2つの異なる場所で\(C_ {I} \) 、クラス教室のコースの他のセクションながら(D_ {I} \)\行います。
任意のアプリケーションの非提出の場合は、学生が完了するためにために、すべての時間を必要とする\(N \)祭り予定のクラスを。学生が最初に変更したい場合は、\(I \)教室のレッスンを、あなたは適用する必要があります。アプリケーションが渡された場合、生徒は最初にすることができます(私は\)\期間教室に行くために\(D_ {I} \)クラス、または教室に残っている\(C_ {I} \)クラス。
あまりにも多くの教室を交換する必要があるため、アプリケーションは介して取得することができないかもしれません。計算することで、牛肉は、まず交換するアプリケーションを見つける\を(私は\)当然の建物部分は、アプリケーションの確率が既知の実数である場合には、\(K_ {I} \) 、およびアプリケーションの異なるコースのため、確率が渡されます彼らは互いに独立しています。
学校の規則は、すべてのアプリケーションは、唯一の学期の開始前に1時間を提出することができ、それぞれの人が専用にまで選択できます(m個\)\レッスンが適用されます。これは、牛肉は、特定のプログラムの結果の適用上の他のコースに適用するかどうかを決定するのではなく、各レッスン教室の1回の交換に適用するかどうかを決定しなければならないことを意味し、牛肉は教室置き換えるために最善の希望を適用することができます\(M \)のコースを、あなたも終了できない\(m個\)を申請する機会を、さらにコースに適用されない場合があります。
(実際の被写体が始まったばかりである、上記のは雲です)
ので別のコースは違う教室で配置することができるので、クラスの牛肉の間の時間を使用する必要が別の教室に1つの教室から到着しました。牛肉の教室は、空のチョーク白で黒板に書かれた教室、見つかった次のクラスの後の日、\(N \)の数字\(0 \)と\(M \)デジタル\(1 \) 、紙の部分に別の整数を読み取るメモ閉じ次\を(K \) 。
しばらくの間観察された牛肉、見出さ\(K-1 \)も割り切れる(N + M-1。\ \) ランダム黒板上で選択された」場合、好奇心牛肉は疑問\(K \)消去の数この\(K \)彼はボード上の唯一の数までの動作を繰り返した後、一回の操作として、黒板に書かれた新しい番号」などの平均数は、どのように多くの数がかかる場合があります値。明らかに、このプロセスでは、黒板上の各数は合理的、牛肉は大学生で、スコアについての知識を学んだので、あなたはどのように彼がどのように黒板に書かれた合理的な数を気にしないでください。あなたは、この値が大きすぎるので、彼は、値をカウントすることができますしてください、あなたはそれが必要とする必要がある\(10 ^ 9 + 7 \)ラインの係数の値を。
\(入力\)
最初の行の入力は三つの整数含ま\(N、M、K \)を。
\(出力\)
出力用黒板可能な値の最後の数の数を表す整数\(9 + 10 ^ 7 \)は、モジュロ値。
\(サンプル入力1 \)
2 2 2
\(サンプル入力2 \)
3 4 3
\(サンプル入力3 \)
150 150 14
\(サンプル出力1 \)
5
\(サンプル出力2 \)
9
\(サンプル出力3 \)
937426930
\(ヒント\)
最初のサンプルで、\(5 \)の可能な値は\(\ FRAC。1 {{}}。4 \)、\ (\ FRAC。8 {} {}。3 \)、\ (\ FRAC 1} {2} {\)、\ (\ {FRAC。8. 5} {} \)、\ (\ {FRAC。4. 3} {} \)。ここで、\(\ {。FRAC 3. 8}} {\)は、以下の方法によって得ることができます。
- ワイプ\(0 \)と\(1 \) 、ライト(\ \ FRAC 1} {2} {\) 。
- ワイプ\を(\ FRAC {1} { 2} \) と\(1 \) 、ライト(\ \ {FRAC。4. 3} {} \) 。
- ワイプ\(0 \)と\(\ FRAC {3} { 4} \) 、ライト(\ \ FRACを8 {} {}。3 \) 。
データ範囲:
\(1≦N、M≤2000、\)
\(2≤K≤2000、\)
\(1-K \)割り切れるの\(N-M + 1 \) 。
10.サブタスクが満足存在\(1≤N、Mを、K≤10。
\) (サブタスクに依存しない)現在の30分のサブタスク、満足\(K = 2 \)
Tucao
それはありません:あなたは、はい、私はあなたに言った、タイトルとまともなXiaopenの友人は非常に興奮して見ました\(2016 \)で\(TGの\)元のタイトルそれの?!!!
しかし、テーマへの言葉の本質に今回ようやく洞察
あなたはプレートを死ぬことはないことを確実にするために、立ち上がって、質問の顔を変えた男
TMDの顔の質問は前にああ主題とは何かを持っています
考え
慣例により、参照学生は最善を尽くす質問の数の数とは、モジュロを必要とし、我々は最初に考える\(DP \)
我々は観察し、各撮影\(k個\)の平均数は、好きではないされて\(K \)ツリーを?!
私たちは考える\(K \)そのリーフノードのツリーを、(0 \)\または\(1 \) 、その息子の平均値は、各非リーフノードであります
だから我々は得ることができます:ツリー\(K \)ツリーがいる\(N + m個\)リーフノード、\(N- \)\(0 \)、\ (m個\)\(1 \を)
セット\(N- \)\(0 \)葉ノードの深されている\(d0_ {I} \)、\ (m個\)\(1 \)葉ノードの深されている\(d1_ {I} \)
その後、我々は、ルートノードの値を取得する簡単として\(\和K ^ { - d1_ {I}} \)
私たちは、すべてのリーフノードの値があるときことを考える(\ 1)\時間、それの根の値がされた(1 \)を\します
したがって、我々は得ることができます
\(\和K ^ { - d1_ {I}} + \和K ^ { - d0_ {I} = 1 \)
今、私たちは、に変換されるものを求めています。
どのように多くの\(X \)のように書くことができる\(\和K ^ { - {I} d1_} \) 形態および\(1-X \)のように書くことができる\(\和K ^ { - d0_ {I} } \)フォーム(私はそれを見つけるが、コードが\(1-X \)数が、すべて同じ)
我々は、これらのことを見出した(\ \ SUM \)は迷惑なので、我々はだろう(X \)を\のように表される\(K \)バイナリ小数点\(0.a_ {1} A_ { 2} A_ {3} ... LEN {} A_ \) 、小数の長さ\(LEN \) 。
これは葉ノード小数部分であるので\(1 \)の値を構成ので\(X \)小数であり、各ある(\ \ sum_ {i = 1 } ^ {LEN} A_ {I} M = \) 、もちろん、それはキャリーケースの不存在下です。セクション一度\(P \)ビット桁上げ、その後\(A_ {P} - = 1、A_ {P + 1} + = K \)、そう\(ヴァル= \ sum_ {I = 1} ^ {LEN} A_ {I} \)
を得ることができる\(ヴァル\当量のM(MOD \) \(K + 1)\)
我々見える\(1-X \) 、同様に、\(1-X \)の長さがなければならない(LEN \)\、それはビットの数として表すことができる\((LEN-1)( K -1)+ K-ヴァルLEN =(1-K)+。1 -Val \) 、容易に入手可能な\(LEN(K-1) \ 1 + -Val)を満たす必要がある\(<= N \)を
私たちの結論は次のステップがされ、プッシュするために行われている(DP \)\ aは
我々は、セット(DP [I]、[J \する ] \) 第小数点表す\(iは\)ビットの番号の前に位置しており、(J \)\プログラムの数を
そこ小数点接尾辞ではないためと\(0 \)ので、我々は状態を追加する必要があります\(k個\)を示しかどうかなど、\(0 \)
私たちは、\(DP \)あなたが使用することを検討することができたときに、プレフィックスと\(合計\)の最適化
\(PS:\)を開くことを忘れないでください\(ロング\) \(ロング\)
コード:
#include<bits/stdc++.h>
using namespace std;
const long long N=2010,mod=1e9+7;
long long sum[N];
long long f[N<<1][N][2];
long long n,m,k;
int main()
{
scanf("%lld %lld %lld",&n,&m,&k);
f[0][0][0]=1;
long long ans=0ll;
for(long long i=1;i<=max(n,m)*2;i++)
{
sum[0]=(f[i-1][0][0]+f[i-1][0][1])%mod;
for(long long j=1;j<=n;j++)
sum[j]=(sum[j-1]+(f[i-1][j][0]+f[i-1][j][1])%mod)%mod;
for(long long j=0;j<=n;j++)
{
f[i][j][0]=(sum[j]-sum[j-1])%mod;
if(j)
{
if(j>=k)f[i][j][1]=(sum[j-1]-sum[j-k]+mod)%mod;
else f[i][j][1]=(sum[j-1]+mod)%mod;
}
}
for(long long j=0;j<=n;j++)
{
if(j%(k-1)==n%(k-1)&&(i*(k-1)-j+1)%(k-1)==m%(k-1)&&i*(k-1)-j+1<=m)ans=(ans+f[i][j][1])%mod;
}
}
printf("%lld",ans);
return 0;
}