CF708E Student's Camp
题解
你考虑暴力怎么做。
用 \(f_{i,l,r}\) 表示到达第 \(i\) 行,左右边界为 \(l\) 到 \(r\) 时联通的概率,那么状态转移式是:
\[f_{i,l,r}=\text{cal}(l,r)\cdot\sum_{[l',r']\cap[l,r]\ne\empty}f_{i-1,l',r'}
\]
然后这个东西直接做必然是 \(O(nm^2)\) 的,非常不优美,所以我们要考虑优化。
我们观察这个转移式的求和,发现其可以被拆成三个求和式的互相加减,即
\[f_{i,l,r}=\text{cal}(l,r)\cdot(\sum f_{i-1,l',r'}-\sum_{r'<l}f_{i-1,l',r'}-\sum_{l'>r}f_{i-1,l',r'})
\]
我们定义
\[F(i)=\sum f_{i,l,r}\\
L(i,j)=\sum_{r<j}f_{i,l,r}\\
R(i,j)=\sum_{l>j}f_{i,l,r}
\]
即
\[f_{i,l,r}=\text{cal}(l,r)\cdot(F(i-1)-L(i-1,l)-R(i-1,r))
\]
可以比较轻易的得到, \(L(i,j)=R(i,m-j+1)\) ,所以式子又变成了
\[f_{i,l,r}=\text{cal}(l,r)\cdot(F(i-1)-L(i-1,l)-L(i-1,m-r+1))
\]
那我们最后的答案就是 \(F(n)\) 。
考虑我们定义的这几个东西怎么转移。
我们再定义
\[L'(i,j)=\sum_{r=j}f_{i,l,r}
\]
那么显然
\[L(i,j)=\sum_{k<j}L'(i,k)\\
F(i)=\sum L'(i,k)
\]
我们再考虑如何求我们再定义的这个东西,我们将 \(f\) 的转移式子带进去。
\[L'(i,j)=\sum_{r=j}f_{i,l,r}\\
=\sum_{r=j}\text{cal}(l,r)\cdot(F(i-1)-L(i-1,l)-L(i-1,m-r+1))\\
=\sum_{l\le j}\text{cal}(l,j)\cdot(F(i-1)-L(i-1,l)-L(i-1,m-j+1))\\
\]
发现不是很好搞了,我们考虑再定义一个前缀和
\[\text{cal}'(i,j)=\sum_{l=i}^j\text{cal}(l,j)
\]
这个东西可以在一开始预处理好,复杂度是 \(O(m^2)\) 的。
然后继续推
\[L'(i,j)=(F(i-1)-L(i-1,m-j+1))\cdot\text{cal}'(1,j)-\sum_{l\le j}\text{cal}(l,j)\cdot L(i-1.l)\\
=(F(i-1)-L(i-1,m-j+1))\cdot\text{cal}'(1,j)-\sum_{l\le j}\text{cal}(l,j)\cdot\sum_{k<l}L'(i-1,k)\\
=(F(i-1)-L(i-1,m-j+1))\cdot\text{cal}'(1,j)-\sum_{k<j}L'(i-1,k)\cdot\text{cal}'(k+1,j)\\
\]
我不行了。
高啊,应该把 \(\text{cal}\) 拆开来搞。
\[\text{cal}(l,r)=func(l-1)\cdot func(m-r)\\
L'(i,j)=\sum_{l\le j}\text{cal}(l,j)\cdot(F(i-1)-L(i-1,l)-L(i-1,m-j+1))\\
=func(m-j)((F(i-1)-L(i-1,m-j+1))\cdot\sum_{l\le j}func(l-1)-\sum_{l\le j}func(l-1)\cdot L(i-1,l)))
\]
然后求一下 \(\sum_{l\le j}func(l-1)\) 和 \(\sum_{l\le j}func(l-1)\cdot L(i-1,l)\) 即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1505,T=1e5+5;
const int MOD=1e9+7;
int n,m,a,_a,b,t;
int frac[T],ifrac[T];
int ksm(int x,int k){
int res=1;
for(;k;k>>=1,x=x*x%MOD)
if(k&1) res=res*x%MOD;
return res;
}
int C(int n,int m){
if(n<m||n<0||m<0) return 0;
return frac[n]*ifrac[m]%MOD*ifrac[n-m]%MOD;
}
int f[N],g[N],h[N],func[T],sum[N];
signed main(){
cin>>n>>m>>a>>b>>t;
a=a*ksm(b,MOD-2)%MOD,_a=(1-a+MOD)%MOD;
frac[0]=1;
for(int i=1;i<=t;++i) frac[i]=frac[i-1]*i%MOD;
ifrac[t]=ksm(frac[t],MOD-2);
for(int i=t;i>=1;--i) ifrac[i-1]=ifrac[i]*i%MOD;
for(int i=0;i<=t;++i) func[i]=C(t,i)*ksm(a,i)%MOD*ksm(_a,t-i)%MOD;
for(int i=1;i<=m;++i) sum[i]=(sum[i-1]+func[i-1])%MOD;
g[m]=1;
for(int i=1;i<=m+1;++i) f[i]=(f[i-1]+g[i-1])%MOD;
for(int i=1;i<=m;++i) h[i]=(h[i-1]+f[i]*func[i-1])%MOD;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j) g[j]=((f[m+1]-f[m-j+1]+MOD)*sum[j]%MOD-h[j]+MOD)%MOD*func[m-j]%MOD;
for(int j=1;j<=m+1;++j) f[j]=(f[j-1]+g[j-1])%MOD;
for(int j=1;j<=m;++j) h[j]=(h[j-1]+f[j]*func[j-1])%MOD;
}
return printf("%lld\n",f[m+1]),0;
}

浙公网安备 33010602011771号