题意: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.