给你两个人的分数a,b
然后两个人各自在[−k,k]之间随机等可能选,然后加到自己的分数上
然后t轮之后,第一个人分数比第二个人高的情况,有多少种
有一个暴力的O(k^2 t^2)的算法,很容易想到,可以利用前缀和的方法来进行优化,得到O(kt^2)的算法。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int mod=1e9+7; const int mid=100000; int a,b,k,t; LL dp[105][200005]; LL pre[200005]; LL ans; int main() { cin>>a>>b>>k>>t; dp[0][mid]=1; for(int i=1; i<=t; i++) { for(int j=0; j<=mid*2; j++) if(dp[i-1][j]) //判断是否会产生新的方案,是的话,就打上标记,再通过求前缀和得到新的dp[i][j] { dp[i][j-k]=(dp[i][j-k]+dp[i-1][j])%mod; dp[i][j+k+1]=(dp[i][j+k+1]-dp[i-1][j]+mod)%mod; } for(int j=1; j<=mid*2; j++) dp[i][j]=(dp[i][j]+dp[i][j-1])%mod; //至此,dp[i][j]表示经过i轮之后,一个人共选分为j-mid的方案数 } pre[0]=dp[t][0]; for(int j=1; j<=mid*2; j++) pre[j]=(dp[t][j]+pre[j-1])%mod; //pre[i]记录,一个人t轮之后所得分数<=j-mid的方案总数,这是一个前缀和 for(int j=b-a+1; j<=2*mid; j++) ans=(ans+1ll*dp[t][j]*pre[min(mid*2,j-(b-a+1))])%mod; cout<<ans<<endl; }