【题解】CF712Dメモリとスコア(DP)

説明

\(AB \)ゲームをプレイし、彼らが遊ぶ\(T \)ラウンドを

一人あたりからランダム確率など\ - ([K、K] \) の合計得点を取るでは数字より高いスコアの勝利に追加されます

既知\(A、B \)をそれぞれ初期\(、B \)ポイント、勝利のプログラム番号を聞いてどのように多くであります

解答\(\ MOD十億七\)

\(A、B、T \ leqslant 100、K \ leqslant \ 1000)

溶液

直接我々は特に嫌な状態と転送を得ることができ、この質問を考えてみます。

\(F [I] [J ] [K] \) 前方を表す\(Iは\)ホイール\(A \)画分である\(J \) \(Bの\)画分である\(Kを\)のプログラムの数。

私たちは、転送があることがわかった\(* 1000年100 *(100)* 1000年*(100)* * 1000年1000年\)(少なくとも私はこの複雑さを転送します

トップに住むこの、。

私たちは、この状態は、我々は実際には2あなたは最終的に計算することができ、プログラムの数には何の影響も個人的な決定であることを見つける何を最適化しています

言い換えると、二人の決定は、私たちは二人である意思決定の選択肢の数を考慮して、それらを一緒に掛けることができ、独立しています。

その後、状態は次のようになります。

\(F1 [I]、[J ]、F2 [I] [J] \) を表している\(A \)\(B \)スコアである(J \)\プログラム番号。だから、毎回、私たちは現在のために、少しだけを列挙するために移動し、\(\) \(Bの\)を選択するにはどのような。

最後に、十分な合併。

複雑\(* 100 100 *(1000)* 1000年\) (あなたは以上になりますかのように

まず、暴力的なコードを置きます:

#include <bits/stdc++.h>
using namespace std;

const int N=105,M=N*1000*2,P=1000000007;
int dp1[2][M],dp2[2][M],sum1[M],sum2[M];

int main(){
    int a=0,b=0,k=0,t=0;
    scanf("%d%d%d%d",&a,&b,&k,&t);
    a+=1e5; b+=1e5;
    dp1[0][a]=dp2[0][b]=1;
    for(int i=1;i<=t;++i){
        int now=i%2,pre=(i-1)%2;
        memset(dp1[now],0,sizeof(dp1[now]));
        memset(dp2[now],0,sizeof(dp2[now]));
        for(int j=-k*i;j<=k*i;++j){
            int l=max(-k*(i-1),j-k),r=min(k*(i-1),j+k);
            for(int p=l;p<=r;++p){
                dp1[now][a+j]+=dp1[pre][a+p];
                dp1[now][a+j]%=P;
                dp2[now][b+j]+=dp2[pre][b+p];
                dp2[now][b+j]%=P;
            }
        }
    }
    int ans=0;
    for(int i=a-k*t;i<=a+k*t;++i)
        for(int j=b-k*t;j<i;++j)
            ans+=(long long)dp1[t%2][i]*dp2[t%2][j]%P,ans%=P;
    ans=(ans%P+P)%P;
    printf("%d\n",ans);
    return 0;
}

頭の上にああ、我々は、最適化する必要があります。

私たちは、現在選択されて、その後、転送が最適化されている場合は何を列挙するために使用するための式を見つけることができ、私たちはその事実を見てみましょう。(Pが作動しています)。

実際には、この部分は何尋ねるです

\(\ sum_ {P = JK} ^ {J + K} DP [I-1] [A + P] \)

\(j個\)は、当社の現在の列挙の付加価値の割合です。

だから我々は、プレフィックスのこの部分などのために祈ります

だから我々は、最も重要な入れ\(1000 \)を取り除くために

複雑\(* 100 100 *(1000)\) (バッチは安定していました。

私たちは、CFの評価機を信じています!

#include <bits/stdc++.h>
using namespace std;

const int N=105,M=N*1000*2,P=1000000007;
int dp1[2][M],dp2[2][M],sum1[M],sum2[M];

int main(){
    int a=0,b=0,k=0,t=0;
    scanf("%d%d%d%d",&a,&b,&k,&t);
    a+=1e5; b+=1e5;
    dp1[0][a]=dp2[0][b]=1;
    sum1[a]=sum2[b]=1;
    for(int i=1;i<=t;++i){
        int now=i%2;
        memset(dp1[now],0,sizeof(dp1[now]));
        memset(dp2[now],0,sizeof(dp2[now]));
        for(int j=-k*i;j<=k*i;++j){
            int l=max(-k*(i-1),j-k),r=min(k*(i-1),j+k);
            dp1[now][a+j]+=(sum1[r+a]-sum1[l+a-1])%P;
            dp1[now][a+j]%=P;
            dp2[now][b+j]+=(sum2[r+b]-sum2[l+b-1])%P;
            dp2[now][b+j]%=P;
        }
        for(int j=1;j<M;++j){
            sum1[j]=sum1[j-1]+dp1[now][j];
            sum1[j]%=P;
            sum2[j]=sum2[j-1]+dp2[now][j];
            sum2[j]%=P;
        }
    }
    int ans=0;
    for(int i=1;i<M;++i)
        ans+=(long long)sum2[i-1]*dp1[t%2][i]%P,ans%=P;
    ans=(ans%P+P)%P;
    printf("%d\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/JCNL666/p/11240934.html