【CF712D】Memory and Scores(概率,DP,前缀和)

题意:AB两人玩一个游戏,两人玩t轮

每人每次随机且等概率从[-k,k]中取一个数字加到总得分中 得分高者赢

已知A B初始分别有a b分,问A取得胜利的概率是多少

 (1 ≤ a, b ≤ 100, 1 ≤ k ≤ 1000, 1 ≤ t ≤ 100)

为了避免小数精度问题答案*(2k+1)^t mod 1000000007

空间限制512M

思路:先来简化问题

首先这必然是一个DP或递推

因为空间不足以暴力保存AB当前各自的分数,而且考虑后会发现只有两人得分当前的差对后面的转移有用,具体的分数并没有用

所以设计出dp[i,j] 表示当前进行到第I轮,A-B分数为J的概率

其次两人玩T轮等价于一人玩2T轮,因为分数的概率是对称的

而状态dp[i,j]对dp[i+1,j-k]到dp[i+1,j+k]有累加的贡献

2*t*k庞大的状态总数决定了只能O(1)转移

又因为转移到的状态下标是连续的 所以想到前缀和

注意下标不能越界

 1 const mo=1000000007;
 2 var dp:array[0..1,0..420000]of longint;
 3     a,b,k,t,tmp,v,i,j,ans,mx:longint;
 4 
 5 function min(x,y:longint):longint;
 6 begin
 7  if x<y then exit(x);
 8  exit(y);
 9 end;
10 
11 function max(x,y:longint):longint;
12 begin
13  if x>y then exit(x);
14  exit(y);
15 end;
16 
17 begin
18  readln(a,b,k,t);
19  mx:=2*t*k+1000;
20  dp[0,a-b+mx]:=1;
21  dp[0,a-b+mx+1]:=mo-1;//此处已经是前缀和的写法 相当于-1
22  for i:=1 to 2*t do
23  begin
24   tmp:=0; v:=1-v;
25   for j:=0 to mx*2 do
26   begin
27    tmp:=(tmp+dp[1-v,j]) mod mo;
28    dp[1-v,j]:=0;
29    dp[v,max(j-k,0)]:=(dp[v,max(j-k,0)]+tmp) mod mo;
30    dp[v,min(j+k+1,mx*2)]:=(dp[v,min(j+k+1,mx*2)]-tmp+mo) mod mo;
31   end;
32  end;
33  tmp:=0;
34  for i:=0 to mx*2 do
35  begin
36   tmp:=(tmp+dp[v,i]) mod mo;
37   if i>mx then ans:=(ans+tmp) mod mo;
38  end;
39  writeln(ans);
40 end.

 

posted on 2016-09-11 20:47  myx12345  阅读(699)  评论(0编辑  收藏  举报

导航