codeforces 712D

来源:互联网 发布:软件著作权好处 编辑:程序博客网 时间:2024/06/13 23:33

题目大意

两个人玩游戏,第一个人最开始分数是a,第二个人最开始分数是b,总共玩t轮,每一轮两人会随机的在区间[k,k]2k+1个数中随机拿一个,并加到自己的分数中。
问第一个人最后赢的概率是多少。
将概率乘(2k+1)t以保证输出的是一个整数,并将整数mod109+7.

解题思路

fi,j表示已经玩了i轮,第一个人比第二个人多j分的概率。
易得,两个人都是从[k,k]取数,所以相当于游戏玩2t轮,每一轮中fi,j都会对fi+1,j,kjjk贡献。
那么我们枚举j,并在fi+1,jk处打+1标记,在fi+1,j+k+1处打-1标记,即可前缀和求出fi+1.

参考代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define maxk 1005#define maxt 105#define maxn (maxk * maxt * 4+505)#define add 200200#define mx (add * 2)#define mo 1000000007#define max(a,b) (((a) > (b)) ? a : b)#define min(a,b) (((a) < (b)) ? a : b)using namespace std;int f[2][maxn],sum[maxn];int a,b,k,t;int now;int main(){    cin>>a>>b>>k>>t;    f[now][a-b+add]=1;    f[now][a-b+add+1]=mo-1;    fo(i,1,2*t) {        int ad=0;        fo(j,0,mx) {            ad=(ad+f[now][j]) % mo;            f[now][j]=0;            f[now ^ 1][max(j-k,0)]=(f[now ^ 1][max(j-k,0)]+ad) % mo;            f[now ^ 1][min(j+k+1,mx)]=(f[now ^ 1][min(j+k+1,mx)]-ad+mo) % mo;        }        now^=1;    }    int ad=0,ans=0;    fo(i,0,mx) {        ad=(ad+f[now][i]) % mo;        if (i>add) ans=(ans+ad) % mo;    }    cout<<ans;    return 0;}
1 0
原创粉丝点击