HDU多校2020 第七场 E-Expectation(概率DP-算贡献的期望DP

题意:http://acm.hdu.edu.cn/showproblem.php?pid=6848

有n个小球,n+1个桶还有他们分别在数轴上的位置,交错排列,每次随机选一个小球往随机一个方向滚,遇到洞就掉下去,小球滚进洞后其他球可以在它上面溜过去。

问所有小球滚动距离的期望。

思路:

简单~(你tm在胡扯吧

 

 

具体还是有点复杂的。

题解是算每条边经过次数的期望,小球两边的线次数期望一定相同,洞两边的期望最多差1次,然后我们要算的是这条线到下一条线期望的增量,由于最多相差1次 所以权值都是*1 or *-1 or *0,可以简单的记作加概率,也就是算右边球先进洞的概率 减 左边球先进洞的概率

首先第一条线题解是类似每次选一条线合并三条线,所以上面是(2*n-1)的双阶乘(一开始还以为是阶乘的阶乘||,太蒟蒻了)

然后我又想了一个n^2算a1的方法(太草了

本地卡在了4.9,后来用了读入挂过了

之后dp转移的话,大致就是每次你之间选洞两边的可以相互抵消,选其他相对于子问题

放上我的n^2算a1的代码

 1 ll qpow(ll a,ll b,ll mod){
 2     ll ans;
 3 //    a%=mod;
 4     ans=1;
 5     while(b!=0)
 6     {
 7         if(b&1)
 8             ans=(ans*a)%mod;
 9         b/=2;
10         a=(a*a)%mod;
11     }
12     return ans;
13 }
14 
15 ll a[N*2],er[N*2];
16 ll _[N*2];
17 ll _inv[N*2];
18 ll inv[N*2];
19 ll inv_ff[N*2];
20 
21 void Init(){
22     _[0]=_[1]=1;
23     er[0]=1;
24     for(int i=2;i<N*2;++i)_[i]=_[i-1]*i%mod;
25     for(int i=1;i<N*2;++i)er[i]=er[i-1]*2%mod;
26     for(int i=0;i<N*2;++i)inv_ff[i]=qpow(_[i]*er[i]%mod,mod-2,mod),_inv[i]=qpow(_[i],mod-2,mod);
27     for(int i=0;i<N*2;++i)inv[i]=qpow(i,mod-2,mod);
28 }
29 ll A(int n,int m){
30     return _[n+m]*_inv[n]%mod*_inv[m]%mod;
31 }
32 ll dis(int x,int y){
33     return llabs(a[x]-a[y])%mod;
34 }
35 ll F[N*2];
36 ll f(int n)
37 {
38     if(F[n])return F[n];
39     int res=0;
40     for(int i=2;i<=n;i+=2)
41     {
42         int X=i-2;
43         int Y=n-i;
44         res+=A(X/2+1,Y/2)*f(X)%mod*f(Y)%mod;
45         res%=mod;
46     }
47     F[n]=res;
48     return res;
49 }
50 
51 ll dp[N][N];
52 void pre()
53 {
54     int n=3003;
55     for(int i=1;i<=n;++i)
56     {
57         dp[0][i]=(1-f(i*2)*inv_ff[i]%mod+mod)%mod;
58         dp[i][0]=-dp[0][i];
59         //    cout << i << endl;
60         for(int j=1;j<i;++j)
61         {
62             int L=j,R=i-j;
63             dp[L][R]=((2*L-1)*dp[L-1][R]%mod+(2*R-1)*dp[L][R-1]%mod)%mod*inv[2*i]%mod;
64         }
65     }
66 }
67 
68 void solve()
69 {
70     int n;
71     cin>>n;
72     int real=n;
73     n=n*2+1;
74     for(int i=1;i<=n;++i)cin>>a[i];
75     ll ans=0;
76     ll res=0;
77     for(int i=1;i<=n-1;++i)
78     {
79         int L=(i-1)/2;
80         if(i&1)res=(res+dp[L][real-L])%mod;
81         ans+=res*dis(i,i+1)%mod;
82         ans%=mod;
83     }
84     cout<<(ans+mod)%mod;
85 }
86 
87 int main()
88 {
89     Init();
90     F[0]=1;
91     pre();
92     int T;
93     cin>>T;
94     while(T--)solve();
95     return 0;
96 }

 

posted @ 2020-08-12 21:49  ZMWLxh  阅读(361)  评论(3编辑  收藏  举报