题目链接https://codeforces.com/gym/101480/attachments
题意
给出一个矩阵,第一行是数组 t t t,第一列是数组 l l l,其余的值为 F [ i ] [ j ] = a F [ i ] [ j − 1 ] + b F [ i − 1 ] [ j ] + c F[i][j]=aF[i][j-1]+bF[i-1][j]+c F[i][j]=aF[i][j−1]+bF[i−1][j]+c。问 F [ n ] [ n ] % 1 e 6 + 3 F[n][n]\%1e6+3 F[n][n]%1e6+3的值是多少
题解
对每个 t [ i ] t[i] t[i]和 l [ i ] l[i] l[i]考虑计算出他们的系数。比如对于 t [ 2 ] t[2] t[2],它在每个位置的系数可以列出来:
t 2 t2 t2 | − - − | − - − | − - − | . . . ... ... |
---|---|---|---|---|
C 1 0 a 0 b 1 C_1^0a^0b^1 C10a0b1 | C 2 1 a 1 b 1 C_2^1a^1b^1 C21a1b1 | C 3 2 a 2 b 1 C_3^2a^2b^1 C32a2b1 | C 4 3 a 3 b 1 C_4^3a^3b^1 C43a3b1 | . . . ... ... |
C 2 0 a 0 b 2 C_2^0a^0b^2 C20a0b2 | C 3 1 a 1 b 2 C_3^1a^1b^2 C31a1b2 | C 4 2 a 2 b 2 C_4^2a^2b^2 C42a2b2 | C 5 3 a 3 b 2 C_5^3a^3b^2 C53a3b2 | . . . ... ... |
C 3 0 a 0 b 1 C_3^0a^0b^1 C30a0b1 | C 4 1 a 1 b 3 C_4^1a^1b^3 C41a1b3 | C 5 2 a 2 b 3 C_5^2a^2b^3 C52a2b3 | C 6 3 a 3 b 3 C_6^3a^3b^3 C63a3b3 | . . . ... ... |
C 4 0 a 0 b 1 C_4^0a^0b^1 C40a0b1 | C 5 1 a 1 b 4 C_5^1a^1b^4 C51a1b4 | C 6 2 a 2 b 4 C_6^2a^2b^4 C62a2b4 | C 7 3 a 3 b 4 C_7^3a^3b^4 C73a3b4 | . . . ... ... |
. . . ... ... | . . . ... ... | . . . ... ... | . . . ... ... | . . . ... ... |
所以对于每个
t
[
i
]
t[i]
t[i]和
l
[
i
]
l[i]
l[i]都可以
O
(
1
)
O(1)
O(1)的计算出他在
F
[
n
]
[
n
]
F[n][n]
F[n][n]上的贡献。
然后就是多加上的
c
c
c了,一样的稍微列一下就可以发现它是帕斯卡矩阵的前缀和,也就是
∑
i
=
0
n
−
2
∑
j
=
0
n
−
2
C
i
+
j
i
a
i
b
j
\sum{_{i=0}^{n-2}}\sum{_{j=0}^{n-2}}C{_{i+j}^{i}}a^ib^j
∑i=0n−2∑j=0n−2Ci+jiaibj,比上面的表多了第一行,然后是求整个表的和。
关于这个有一些能够
O
(
n
)
O(n)
O(n)的神仙做法,我这里写的是题解的
N
T
T
NTT
NTT做法
把式子变换一下即可:
∑
i
=
0
n
−
2
∑
j
=
0
n
−
2
C
i
+
j
i
a
i
b
j
\sum{_{i=0}^{n-2}}\sum{_{j=0}^{n-2}}C{_{i+j}^{i}}a^ib^j
∑i=0n−2∑j=0n−2Ci+jiaibj
=
∑
i
=
0
n
−
2
∑
j
=
0
n
−
2
(
i
+
j
)
!
i
!
j
!
=\sum_{i=0}^{n-2}\sum_{j=0}^{n-2}\frac{(i+j)!}{i!j!}
=i=0∑n−2j=0∑n−2i!j!(i+j)!
=
∑
i
=
0
n
−
2
∑
j
=
0
n
−
2
(
i
+
j
)
!
a
i
i
!
b
j
j
!
=\sum_{i=0}^{n-2}\sum_{j=0}^{n-2}(i+j)!\frac{a^i}{i!}\frac{b^j}{j!}
=i=0∑n−2j=0∑n−2(i+j)!i!aij!bj
=
∑
i
=
0
n
−
2
∑
j
=
0
n
−
2
f
(
i
+
j
)
g
(
i
)
h
(
j
)
=\sum_{i=0}^{n-2}\sum_{j=0}^{n-2}f(i+j)g(i)h(j)
=i=0∑n−2j=0∑n−2f(i+j)g(i)h(j)
=
∑
k
=
0
2
n
−
4
f
(
k
)
(
g
∗
h
(
k
)
)
=\sum_{k=0}^{2n-4}f(k)(g*h(k))
=k=0∑2n−4f(k)(g∗h(k))
题目给出来的模数
1
e
6
+
3
1e6+3
1e6+3刚好等于
500001
∗
2
+
1
500001*2+1
500001∗2+1,所以可以直接套上
N
T
T
NTT
NTT去求。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,int> piir;
const ll N=4e6+7;
const ll inf=1e18;
const ll mod=1e6+3;
const db pi=acos(-1);
ll g[N],h[N];
namespace NTT
{
typedef long long ll;
const ll MOD=1945555039024054273LL;
const ll g=5;
ll mul(ll x,ll y){
return (x*y-(ll)(x/(long double)MOD*y+1e-6)*MOD+MOD)%MOD;
}
ll qpow(ll a,ll k){
ll res=1LL;
while(k>0){
if(k&1)res=mul(res,a);
a=mul(a,a);
k>>=1;
}
return res;
}
void change(ll y[],int len){
for(int i=1,j=len/2;i<len-1;i++){
if(i<j)swap(y[i],y[j]);
int k=len/2;
while(j>=k){
j-=k;
k/=2;
}
if(j<k)j+=k;
}
}
void ntt(ll y[],int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
ll wn=qpow(g,(MOD-1)/h);
if(on==-1)wn=qpow(wn,MOD-2);
for(int j=0;j<len;j+=h){
ll w=1LL;
for(int k=j;k<j+h/2;k++){
ll u=y[k];
ll t=mul(w,y[k+h/2]);
y[k]=(u+t)%MOD;
y[k+h/2]=(u-t+MOD)%MOD;
w=mul(w,wn);
}
}
}
if(on==-1){
ll t=qpow(len,MOD-2);
for(int i=0;i<len;i++)
y[i]=mul(y[i],t);
}
}
void cal(ll x1[],ll x2[],ll tot){
int len=1;
while(len<2*tot)len<<=1;
ntt(x1,len,1);
ntt(x2,len,1);
for(int i=0;i<len;i++)
x1[i]=mul(x1[i],x2[i]);
ntt(x1,len,-1);
}
}
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
b>>=1;a=a*a%mod;
}
return res;
}
ll n,a,b,c;
ll l[N],t[N];
ll fac[N],iv[N];
ll comb(ll n,ll m){return fac[n]*iv[n-m]%mod*iv[m]%mod;}
int main()
{
fac[0]=1;
for(ll i=1;i<N;i++) fac[i]=(fac[i-1]*i)%mod;
for(ll i=0;i<N;i++) iv[i]=qpow(fac[i],mod-2);
scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
for(int i=1;i<=n;i++){
scanf("%lld",&l[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&t[i]);
}
ll ans=0;
for(int i=2;i<=n;i++){
ans=(ans+t[i]*comb(2*n-i-2,n-i)%mod*qpow(a,n-i)%mod*qpow(b,n-1)%mod)%mod;
ans=(ans+l[i]*comb(2*n-i-2,n-i)%mod*qpow(a,n-1)%mod*qpow(b,n-i)%mod)%mod;
}
for(ll i=0;i<=n-2;i++){
g[i]=qpow(a,i)*iv[i]%mod;
h[i]=qpow(b,i)*iv[i]%mod;
}
NTT::cal(g,h,n-1);
for(ll i=0;i<=2*n-4;i++){
g[i]%=mod;
ans=(ans+c*fac[i]%mod*g[i]%mod)%mod;
}
printf("%lld\n",ans);
}