Codeforces-1473-G. Tiles (Vandermonde Convolution + Fast Number Theory Transformation NTT)

topic

Portal
Insert picture description here

Ideas

This is the idea of ​​the solution: the portal.
Insert picture description here
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=1mCa+bbk+ja n si,k

  1. Explain i,j,kthe significance of it. i,jRefer to the discussion from now on itill the first column i+1order of the columns of the first jposition; krepresentatives from the enumeration iorder of the columns on kthe starting position.
    Insert picture description here
  2. Then we look at from (i,k)the (i+1,j)contribution of the former enumerate a number of times down t, 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=0j+bkCatCbjk+bta 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+bjk+ba n si,k
    So to kfind 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

*/

Guess you like

Origin blog.csdn.net/jackypigpig/article/details/113030320