[CERC2015]Frightful Formula
Description
定义一个矩阵 (F),给定其第一行和第一列,其他位置将通过递推方式给出,具体的:
[F_{i,j}=aF_{i,j-1}+bF_{i-1,j}+c
]
求 (F(n,n))。
(nle 2 imes 10^5)。
Solution
首先考虑 (c=0) 的情况,此时原问题可以看作从第二行第二列出发,只能向右或向下走且向右走的权值为 (a),向左走的权值为 (b) 时所有方案的权值积之和。枚举起点,容易写出贡献就是:
[sum_{i=2}^{n}l_iinom{2n-2-i}{n-2}a^{n-1}b^{n-i}+sum_{i=2}^{n}t_iinom{2n-2-i}{n-2}a^{n-i}b^{n-1}
]
这一部分可以暴力 (mathcal O(n)) 计算,接下来考虑 (c) 对答案的贡献,枚举 (c) 在哪一个位置出现,那么它的贡献就是从这个位置到 ((n,n)) 的所有方案的权值积:
[csum_{i=2}^{n}sum_{j=2}^{n}inom{2n-i-j}{n-i}a^{n-j}b^{n-i}\
=csum_{i=2}^{n}dfrac{b^{n-i}}{(n-i)!}sum_{j=2}^{n}dfrac{a^{n-j}(2n-i-j)!}{(n-j)!}
]
这就是一个减法卷积,由于模数为 (10^6+3) ,所以需要使用 (MTT)。
略微有点卡常,考虑优化,回到 (c) 的柿子,改为枚举 (2n-i-j) 试试?
[csum_{t=0}^{2n-4}sum_{i=max(0,t-n+2)}^{n-2}inom{t}{i}a^{t-i}b^i
]
我们想直接大力二项式定理,但好像上标下标不太对,考虑分 (tle n-2) 与 (t>n-2) 分别讨论:
(tle n-2):
[egin{aligned}
&=csum_{t=0}^{n-2}sum_{i=0}^{t}inom{t}{i}a^{t-i}b^i\
&=csum_{t=0}^{n-2}(a+b)^t
end{aligned}
]
(t>n-2):
[egin{aligned}
&=csum_{t=n-1}^{2n-4}sum_{i=t-n+2}^{n-2}inom{t}{i}a^{t-i}b^i\
end{aligned}
]
记 (g_t=sum_{i=t-n+2}^{n-2}dbinom{t}{i}a^{t-i}b^i)。
有:
[egin{aligned}
g_t&=sum_{i=t-n+2}^{n-2}(inom{t-1}{i-1}+inom{t-1}{i})a^{t-i}b^i\
&=asum_{i=t-n+2}^{n-2}inom{t-1}{i}a^{(t-1)-i}b^i+bsum_{i=t-n+2}^{n-2}inom{t-1}{i-1}a^{(t-1)-(i-1)}b^{i-1}\
end{aligned}
]
这玩意很像是 ((a+b)g_{t-1}),但是前者的上下界为 ([t-n+2,n-2]),后者为 ([t-n+1,n-3]),距离 ([t-n+1,n-2]) 都有差距,需要减去多出的部分:
[g_t=(a+b)g_{t-1}-inom{t-1}{t-n+1}a^{n-1}b^{t-n+1}-inom{t-1}{n-2}a^{t-n+1}b^{n-1}\
]
于是直接 (mathcal O(n)) 递推即可。复杂度 (mathcal O(n))。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10,mod=1e6+3;
int n,a,b,c,l[N],t[N],base[N],jc[N],pwa[N],pwb[N],f[N];
inline int ksm(int x,int y){
int ret=1;
for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) ret=1ll*ret*x%mod;
return ret;
}
inline void init(int n){
base[0]=1;
for(int i=1;i<=n;++i) base[i]=1ll*base[i-1]*i%mod;
jc[n]=ksm(base[n],mod-2);
for(int i=n-1;i>=0;--i) jc[i]=1ll*jc[i+1]*(i+1)%mod;
pwa[0]=1;pwb[0]=1;
for(int i=1;i<=n;++i) pwa[i]=1ll*pwa[i-1]*a%mod,pwb[i]=1ll*pwb[i-1]*b%mod;
}
inline int binom(int x,int y){if(x<y) return 0;return 1ll*base[x]*jc[y]%mod*jc[x-y]%mod;}
inline void inc(int &x,int y){x=(x+y>=mod)?x+y-mod:x+y;}
inline int dec(int x,int y){return (x-y<0)?x-y+mod:x-y;}
int main(){
scanf("%d%d%d%d",&n,&a,&b,&c);
init(n<<1);
int ans=0;
for(int i=1;i<=n;++i){
scanf("%d",&l[i]);
if(i>=2) ans=(ans+1ll*l[i]*binom(n-2+n-i,n-2)%mod*pwa[n-1]%mod*pwb[n-i])%mod;
}
for(int i=1;i<=n;++i){
scanf("%d",&t[i]);
if(i>=2) ans=(ans+1ll*t[i]*binom(n-2+n-i,n-2)%mod*pwb[n-1]%mod*pwa[n-i])%mod;
}
int ret=0;
for(int t=0,pw=1;t<=n-2;++t,pw=1ll*pw*(a+b)%mod)
inc(ret,pw);
for(int t=n-1;t<=2*n-4;++t){
if(t==n-1){
f[n-1]=0;
for(int i=1;i<=n-2;++i) f[n-1]=(f[n-1]+1ll*binom(n-1,i)*pwa[n-1-i]%mod*pwb[i])%mod;
}
else{
f[t]=1ll*f[t-1]*(a+b)%mod;
f[t]=dec(f[t],1ll*binom(t-1,t-n+1)*pwa[n-1]%mod*pwb[t-n+1]%mod);
f[t]=dec(f[t],1ll*binom(t-1,n-2)*pwb[n-1]%mod*pwa[t-n+1]%mod);
}
inc(ret,f[t]);
}
ans=(ans+1ll*ret*c)%mod;
printf("%d
",ans);
return 0;
}