题目链接:ZOJ3982 Expected Waiting Time
sol:
-
对于固定的 A S AS AS序列,无论离开休息室的顺序如何,总的等待时长是相同的。一个合法的 A S AS AS序列满足其所有的前缀中 A A A的个数 ≥ \ge ≥ S S S的个数,等价于一个长度为 2 n 2n 2n的括号序列。易知总方案数为第 n n n个卡特兰数,记为 H ( n ) H(n) H(n)
-
现在考虑计算每一个人的贡献。把问题转换为括号序列,则总等待时长相当于在左括号的位置标记 − - −号,在右括号的位置标记 + + +号,求 a [ i ] a[i] a[i]乘上 + / − +/- +/−号后的前缀和。
-
若我们固定一对合法括号 l , r l,r l,r,整个括号序列序列当且仅当 [ l , r ] [l,r] [l,r]区间合法且 [ 1 , l − 1 ] [1,l-1] [1,l−1]和 [ r + 1 , 2 n ] [r+1,2n] [r+1,2n]合法。则总的方案数为 H ( r − l + 1 2 − 1 ) ∗ H ( 2 n − ( r − l + 1 ) 2 ) H(\frac{r-l + 1}{2} - 1) * H(\frac{2n - (r-l+1)}{2}) H(2r−l+1−1)∗H(22n−(r−l+1)),而这对括号的贡献为 a [ r ] − a [ l ] a[r] - a[l] a[r]−a[l]。
-
考虑枚举长度,则总等待时间为
t o t = ∑ L = 2 2 n ∑ i = 1 2 n + 1 − L H ( L 2 − 1 ) H ( 2 n − L 2 ) ( a [ i + L − 1 ] − a [ i ] ) = ∑ L = 2 2 n H ( L 2 − 1 ) H ( 2 n − L 2 ) ∑ i = 1 2 n + 1 − L ( a [ i + L − 1 ] − a [ i ] ) = ∑ L = 2 2 n H ( L 2 − 1 ) H ( 2 n − L 2 ) f ( L ) \begin{aligned} tot &= \sum_{L=2}^{2n} \sum_{i = 1}^{2n+1-L} H(\frac{L}{2} - 1) H(\frac{2n - L}{2}) (a[i+L-1] - a[i]) \\ &= \sum_{L=2}^{2n} H(\frac{L}{2} - 1) H(\frac{2n - L}{2})\sum_{i = 1}^{2n+1-L} (a[i+L-1] - a[i]) \\ &= \sum_{L=2}^{2n} H(\frac{L}{2} - 1) H(\frac{2n - L}{2})f(L) \end{aligned} tot=L=2∑2ni=1∑2n+1−LH(2L−1)H(22n−L)(a[i+L−1]−a[i])=L=2∑2nH(2L−1)H(22n−L)i=1∑2n+1−L(a[i+L−1]−a[i])=L=2∑2nH(2L−1)H(22n−L)f(L)
答案为
a
n
s
=
t
o
t
H
(
n
)
ans = \frac{tot}{H(n)}
ans=H(n)tot
看起来复杂度比较感人。
右边式子化简一下
f
(
L
)
=
∑
i
=
1
2
n
+
1
−
L
(
a
[
i
+
L
−
1
]
−
a
[
i
]
)
=
∑
i
=
1
2
n
+
1
−
L
−
∑
L
2
n
\begin{aligned} f(L) &=\sum_{i = 1}^{2n+1-L} (a[i+L-1] - a[i])\\ &= \sum_{i=1}^{2n+1-L} - \sum_{L}^{2n} \end{aligned}
f(L)=i=1∑2n+1−L(a[i+L−1]−a[i])=i=1∑2n+1−L−L∑2n
发现是个前缀和后缀的形式,
O
(
n
)
O(n)
O(n)预处理一下,于是整个式子就可以
O
(
n
)
O(n)
O(n)计算了。
- 计算卡特兰数可以用
H ( n ) = H ( n − 1 ) 4 n − 2 n + 1 H(n) = H(n-1)\frac{4n-2}{n+1} H(n)=H(n−1)n+14n−2递推计算。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6+10;
ll a[maxn],b[maxn];
ll h[maxn],inv[maxn];
ll sum[maxn];
int n,mod;
void Add(ll &x,ll y){
x += y;
if(x>=mod) x-=mod;
}
void Mul(ll& x,ll y){
x *= y;
if(x>=mod) x %= mod;
}
void init(){
inv[0] = inv[1] = 1;
for(int i = 2;i<= n *2 ;i++) inv[i] = inv[mod % i] * (mod - mod/i) % mod;
h[0] = h[1] = 1;
for(int i = 2;i<= n * 2;i++) h[i] = h[i-1] * (i * 4 - 2) % mod * inv[i+1] % mod;
}
ll qpow(ll a,int b){
ll ret = 1;
while(b){
if(b&1) Mul(ret,a);
Mul(a,a);
b>>=1;
}
return ret;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int A,B;
scanf("%d%d%lld%d%d",&n,&mod,&b[0],&A,&B);
init();
for(int i = 1;i<=n*2;i++) b[i] = (b[i-1] * A + B) % mod;
for(int i = 1;i<=n*2;i++){
a[i] = (a[i-1] + b[i] + 1) % mod;
// cout<<"a[i] = "<<i<<' '<<a[i]<<endl;
}
for(int i = 1;i<=n*2;i++){
sum[i] = sum[i-1];
Add(sum[i],a[i]);
}
ll ans = 0;
for(int i = 1;i<=n;i++){
ll ret = sum[n*2];
Add(ret,mod - sum[i*2 - 1]);
Add(ret,mod - sum[n*2 + 1 - i*2]);
// cout<<"ret1 = "<<i<<' '<<ret<<endl;
Mul(ret,h[i-1]);
Mul(ret,h[n-i]);
Add(ans,ret);
// cout<<"ret2 = "<<i<<' '<<ret<<endl;
}
Mul(ans,qpow(h[n],mod-2));
printf("%lld\n",ans);
}
return 0;
}