topic
Ideas
This is the idea of the solution: the portal.
Let me write down my understanding of the solution.
- First, solve this recursive problem:
a n s i + 1 , j = ∑ k = 1 m C a + b b − k + j a n s i , k ans_{i+1,j}=\sum^{m}_{k=1}{C^{b-k+j}_{a+b} ans_{i,k}} a n si+1,j=k=1∑mCa+bb−k+ja n si,k
- Explain
i,j,k
the significance of it.i,j
Refer to the discussion from now oni
till the first columni+1
order of the columns of the firstj
position;k
representatives from the enumerationi
order of the columns onk
the starting position.
- Then we look at from
(i,k)
the(i+1,j)
contribution of the former enumerate a number of times downt
, you will get such a contribution:
sigma k = 0 J + b - k C AT C BJ - k + b - Tansi, k \ sum^{j+bk}_{k=0} {C^t_a C^{j-k+bt}_b} ans_{i,k}k=0∑j+b−kCatCbj−k+b−ta n si,k
Through Vandermonde convolution, it can be obtained that this formula is actually equal to
C a + bj − k + bansi, k C^{j-k+b}_{a+b} ans_{i,k}Ca+bj−k+ba n si,k
So tok
find a top that and is a recursive formula.
For Vandermonde convolution, please refer to this blog https://blog.csdn.net/qq_42880894/article/details/87814601
With this recurrence, as the solution says, the time complexity calculated for each i is O(n^2)
, then the total time complexity should be O(n^3)
, for 1000, it may time out, so NTT has to be used to speed up.
- Next is my understanding of this NTT question (now QAQ)
Code
The first generation (not using NTT acceleration, will TLE)
#include <cstdio>
#define N 1005
#define Ha 998244353
typedef long long LL;
int n,h,a[N],b[N];
LL jc[10005]; //阶乘
LL ans[N][N<<3];
//快速幂
LL ksm(LL x, LL t) {
LL ret=1;
for (; t; (t>>=1),(x=x*x%Ha)) {
if (t&1) {
ret=ret*x%Ha;
}
}
return ret;
}
//组合数
LL C(LL x, LL y) {
if (y>x || y<0) {
return 0;
}
if (x-y>y) {
y=x-y;
}
LL ret;
ret=jc[x];
ret=ret*ksm(jc[y],Ha-2)%Ha;
ret=ret*ksm(jc[x-y],Ha-2)%Ha;
return ret;
}
int main() {
jc[0]=jc[1]=1;
for (int i=2; i<=10000; i++) {
jc[i]=(jc[i-1]*i)%Ha;
}
scanf("%d",&n);
for (int i=1; i<=n; i++) {
scanf("%d%d",&a[i],&b[i]);
}
ans[0][1]=1;
h=1;
for (int i=1; i<=n; i++) {
for (int j=1,mj=h+a[i]-b[i]; j<=mj; j++) {
LL tmp=0;
for (int k=1; k<=h; k++) {
tmp+=ans[i-1][k]*C(a[i]+b[i],j-k+b[i])%Ha; //核心
tmp%=Ha;
}
ans[i][j]+=tmp;
ans[i][j]%=Ha;
}
h+=a[i]-b[i];
}
LL Ans=0;
for (int i=1; i<=h; i++) {
Ans+=ans[n][i];
Ans%=Ha;
}
printf("%lld\n",Ans);
return 0;
}
/*
2
4 2
2 3
*/