从
(
a
1
,
a
i
)
(a_1, a_i)
(a1,ai) 出发的随机游走,每次随机一个方向将减
1
1
1,直到走到坐标轴上为止。如果停在
(
0
,
a
)
(0,a)
(0,a),对答案的贡献为
a
i
−
a
a_i-a
ai−a。若停在
(
a
,
0
)
(a,0)
(a,0),对答案的贡献为
a
i
a_i
ai。可以写出贡献的式子。
∑
i
=
0
a
i
−
1
i
∗
(
a
1
−
1
+
i
i
)
2
a
1
+
i
+
a
i
(
1
−
∑
i
=
0
a
i
−
1
(
a
1
−
1
+
i
i
)
2
a
1
+
i
)
\sum_{i=0}^{a_i-1}i*\frac{a_1-1+i\choose i}{2^{a_1+i}}+a_i(1-\sum_{i=0}^{a_i-1}\frac{a_1-1+i\choose i}{2^{a_1+i}})
i=0∑ai−1i∗2a1+i(ia1−1+i)+ai(1−i=0∑ai−12a1+i(ia1−1+i))
这个式子推出来需要多枚举,我做的时候就是枚举一些
a
i
a_i
ai找出规律的
前面那项是停留在
(
0
,
a
)
(0,a)
(0,a) 的答案,后面那项是停留在
(
a
,
0
)
(a,0)
(a,0) 的答案。 当
a
i
a_i
ai 增加
1
1
1 的时候,变化的贡献可以在
O
(
1
)
O(1)
O(1) 的时间内得到。(前后都是只增加了一项)
#include<bits/stdc++.h>
#define LL long long int
#define mod 323232323
#define inv2 (mod+1>>1)
int fact[1000001];
int invf[1000001];
int ipw2[1000001];
int P[1000001],E[1000001];
int pow(int x,int y)
{
int ans=1;
while(y)
{
if(y&1)ans=(LL)ans*x%mod;
x=(LL)x*x%mod;
y>>=1;
}
return ans;
}
int C(int x,int y)
{
return (LL)fact[x]*invf[y]%mod*invf[x-y]%mod;
}
int main()
{
ipw2[0]=fact[0]=1;
for(int i=1;i<=1000000;i++)
fact[i]=fact[i-1]*(LL)i%mod;
for(int i=1;i<=1000000;i++)
ipw2[i]=((LL)ipw2[i-1]*inv2)%mod;
invf[1000000]=pow(fact[1000000],mod-2);
for(int i=1000000;i;i--)
invf[i-1]=invf[i]*(LL)i%mod;
P[0]=E[0]=0;
int N,X,hp,ans=0;
scanf("%d%d",&N,&X);
for(int i=0;i<500000;i++)
{
P[i+1]=(P[i]+(LL)C(X+i-1,i)*ipw2[X+i])%mod;
E[i+1]=(E[i]+(LL)C(X+i-1,i)*ipw2[X+i]%mod*i)%mod;
}
N--;
for(int i=0;i<N;i++)
{
scanf("%d",&hp);
ans=(ans+E[hp]+(LL)hp*(mod-P[hp]+1))%mod;
}
printf("%d",(ans+X)%mod);
}
来源:zr