题目描述
解题思路
发现自己还是不会卷积。
考虑暴力的递推式:
f[i][j]=(p∗f[i−1][j]+q∗f[i][j−1]+(p∗α+q∗β)
f
[
i
]
[
j
]
=
(
p
∗
f
[
i
−
1
]
[
j
]
+
q
∗
f
[
i
]
[
j
−
1
]
+
(
p
∗
α
+
q
∗
β
)
,边界是
f[0][j]=b[j]和f[i][0]=a[i]
f
[
0
]
[
j
]
=
b
[
j
]
和
f
[
i
]
[
0
]
=
a
[
i
]
,我们计
inc=(p∗α+q∗β)
i
n
c
=
(
p
∗
α
+
q
∗
β
)
,那么,我们直接考虑一个
f[i][j]
f
[
i
]
[
j
]
的值,它是由许多位置的inc和a[i]和b[j]贡献过来的,然后他对答案的贡献还要乘上h的幂。我们分情况考虑。
对于inc:
我们枚举一个位置(x-i,y-j)对(x,y)的贡献
f[x][y]=∑i=0..x−1∑j=0..y−1Cii+j∗inc∗pi∗qj
f
[
x
]
[
y
]
=
∑
i
=
0..
x
−
1
∑
j
=
0..
y
−
1
C
i
+
j
i
∗
i
n
c
∗
p
i
∗
q
j
对答案的贡献:
∑i=0..x−1∑j=0..y−1Cii+j∗inc∗pi∗qj∗h(n+1)x∗hy
∑
i
=
0..
x
−
1
∑
j
=
0..
y
−
1
C
i
+
j
i
∗
i
n
c
∗
p
i
∗
q
j
∗
h
(
n
+
1
)
x
∗
h
y
所有f对答案的贡献
∑x=1..n∑y=1..n∑i=0..x−1∑j=0..y−1Cii+j∗inc∗pi∗qj∗h(n+1)x∗hy
∑
x
=
1..
n
∑
y
=
1..
n
∑
i
=
0..
x
−
1
∑
j
=
0..
y
−
1
C
i
+
j
i
∗
i
n
c
∗
p
i
∗
q
j
∗
h
(
n
+
1
)
x
∗
h
y
∑i=0..n−1∑j=0..n−1Cii+j∗inc∗pi∗qj∗∑x=i+1..n∑y=j+1..nh(n+1)x∗hy
∑
i
=
0..
n
−
1
∑
j
=
0..
n
−
1
C
i
+
j
i
∗
i
n
c
∗
p
i
∗
q
j
∗
∑
x
=
i
+
1..
n
∑
y
=
j
+
1..
n
h
(
n
+
1
)
x
∗
h
y
∑i=0..n−1∑j=0..n−1Cii+j∗inc∗pi∗qj∗∑x=i+1..nh(n+1)x∑y=j+1..n∗hy
∑
i
=
0..
n
−
1
∑
j
=
0..
n
−
1
C
i
+
j
i
∗
i
n
c
∗
p
i
∗
q
j
∗
∑
x
=
i
+
1..
n
h
(
n
+
1
)
x
∑
y
=
j
+
1..
n
∗
h
y
∑i=0..n−1∑j=0..n−1(i+j)!i!j!∗inc∗pi∗qj∗h(n+1)(i+1) (1−h(n+1)(n−i) )1−hn+1∗hj+1 (1−hn−j )1−h
∑
i
=
0..
n
−
1
∑
j
=
0..
n
−
1
(
i
+
j
)
!
i
!
j
!
∗
i
n
c
∗
p
i
∗
q
j
∗
h
(
n
+
1
)
(
i
+
1
)
(
1
−
h
(
n
+
1
)
(
n
−
i
)
)
1
−
h
n
+
1
∗
h
j
+
1
(
1
−
h
n
−
j
)
1
−
h
我们先令除了组合数的部分的含有i的项和含有j的项分别记为
fa[i],fb[j]
f
a
[
i
]
,
f
b
[
j
]
,那么原式等于
inc∗∑i=0..n−1∑j=0..n−1(i+j)!∗fa[i]∗fb[j]
i
n
c
∗
∑
i
=
0..
n
−
1
∑
j
=
0..
n
−
1
(
i
+
j
)
!
∗
f
a
[
i
]
∗
f
b
[
j
]
这个用ntt就可以优化了。
具体的,设
F[n]=∑i=0..nfa[i]∗fb[n−i]
F
[
n
]
=
∑
i
=
0..
n
f
a
[
i
]
∗
f
b
[
n
−
i
]
,算出F[]然后
F[i]∗=inc∗i!
F
[
i
]
∗
=
i
n
c
∗
i
!
即可,答案贡献就把每一项算进去即可。
对于a[]:
考虑一个位置(x,0)对所有位置的贡献,注意不能给第0列贡献。
∑x=1..nax∑i=0..n∑j=1..nCj−1i+j−1piqjh(n+1)(x+i)+j
∑
x
=
1..
n
a
x
∑
i
=
0..
n
∑
j
=
1..
n
C
i
+
j
−
1
j
−
1
p
i
q
j
h
(
n
+
1
)
(
x
+
i
)
+
j
∑x=1..naxh(n+1)x∑i=0..n∑j=1..n(i+j−1)!i!(j−1)!piqjh(n+1)ihj
∑
x
=
1..
n
a
x
h
(
n
+
1
)
x
∑
i
=
0..
n
∑
j
=
1..
n
(
i
+
j
−
1
)
!
i
!
(
j
−
1
)
!
p
i
q
j
h
(
n
+
1
)
i
h
j
∑x=1..naxh(n+1)x∑i=0..n(ph(n+1) )ii!∑j=1..n(qh)j(j−1)!∗(i+j−1)!
∑
x
=
1..
n
a
x
h
(
n
+
1
)
x
∑
i
=
0..
n
(
p
h
(
n
+
1
)
)
i
i
!
∑
j
=
1..
n
(
q
h
)
j
(
j
−
1
)
!
∗
(
i
+
j
−
1
)
!
设
f[i]=(ph(n+1) )ii!∑j=1..n(qh)j(j−1)!∗(i+j−1)!
f
[
i
]
=
(
p
h
(
n
+
1
)
)
i
i
!
∑
j
=
1..
n
(
q
h
)
j
(
j
−
1
)
!
∗
(
i
+
j
−
1
)
!
,那么一个位置x的贡献就是f的一个前缀和。
考虑如何算f。
设
G[i]=∑j=1..n(qh)j(j−1)!∗(i+j−1)!
G
[
i
]
=
∑
j
=
1..
n
(
q
h
)
j
(
j
−
1
)
!
∗
(
i
+
j
−
1
)
!
转化为如何快速求出每个g的值。
设
fac[i]=i!,g[j]=(qh)j(j−1)!
f
a
c
[
i
]
=
i
!
,
g
[
j
]
=
(
q
h
)
j
(
j
−
1
)
!
那么
G[i]=∑j=1..ng[j]∗fac[i+j−1]
G
[
i
]
=
∑
j
=
1..
n
g
[
j
]
∗
f
a
c
[
i
+
j
−
1
]
我们发现他们的下标不满足卷积形式,下标加起来是i+2*j-1的,那么考虑把g[]变换一下,使得下标和中的变量只含有i这一项。
g′[n−j+1]=g[j]
g
′
[
n
−
j
+
1
]
=
g
[
j
]
那么
G[i]=∑j=1..ng[n−j+1]∗fac[i+j−1]
G
[
i
]
=
∑
j
=
1..
n
g
[
n
−
j
+
1
]
∗
f
a
c
[
i
+
j
−
1
]
,发现下标和恰好为n+i,那么有
G[i−n]=G′[i]=∑j=0..ig[j]∗fac[i−j]
G
[
i
−
n
]
=
G
′
[
i
]
=
∑
j
=
0..
i
g
[
j
]
∗
f
a
c
[
i
−
j
]
,那么我们把
G′
G
′
卷积出来,就可以得到G了。
此时我们就可以算出f,然后前缀和一下,枚举x,计算贡献。
此外,f(x,0)位置本身的贡献也要记进去。
对于b[]
和a[]是几乎一样的,只需要把 phn+1和qh p h n + 1 和 q h 交换一下,把a[]和b[]交换一下,就完全一样了。
我怎么搞了3h啊…
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
//开 O2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
#define cmin(a,b) (a=(a<b)?a:b)
typedef long long ll;
typedef long long LL;
typedef double db;
const int N=1005+5,mo=998244353;
int ksm(int x,int y)
{
int ret=1;
while (y)
{
if (y&1) ret=1ll*ret*x%mo;
y>>=1;
x=1ll*x*x%mo;
}
return ret;
}
int n,h,alp,bet,p1,p2,q1,q2,p,q,inc,f[N][N],i,j,ph,ans;
int main()
{
freopen("dream.in","r",stdin);
// freopen("dream.out","w",stdout);
scanf("%d %d %d %d",&n,&h,&alp,&bet);
scanf("%d %d %d %d",&p1,&p2,&q1,&q2);
p=1ll*p1*ksm(p2,mo-2)%mo;
q=1ll*q1*ksm(q2,mo-2)%mo;
fo(i,1,n) scanf("%d",f[i]+0);
fo(i,1,n) scanf("%d",f[0]+i);
inc=(1ll*p*alp+1ll*q*bet)%mo;
fo(i,1,n) fo(j,1,n)
f[i][j]=(1ll*p*f[i-1][j]+1ll*q*f[i][j-1]+inc)%mo;
ph=1;
fo(i,0,n) fo(j,0,n)
{
ans=(ans+1ll*f[i][j]*ph)%mo;
ph=1ll*ph*h%mo;
}
printf("%d\n",ans);
}