"蔚来杯"2022牛客暑期多校训练营2 E Falfa with Substring

赛时做出来了。

考虑能求出 \(f[i][j]=f[i-3][j-1]+f[i-1][j],\forall j\in [1,n]\),也就是说在 \(n\) 个空选 \(j\) 个 bit,转为有 \(n-2\) 个空,选 \(j\) 个空,每个空之间至少间隔 2 个空(选左端点)。

oeis 一下,发现就是经典多次前缀和结论,\((1+x^1+x^2...)^a\) 可以认为从 \((1,0)\) 游走到 \((a,b)\) 的方案数,也就是源点有无限 1,向外散。

然后就是其他随便选,二项式反演,NTT。

后面套路讲解

#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}
const int N=(int)(6e6+5),M=N,mod=998244353,G=3;

int fpow(int x,int y) {
	int res=1;
	while(y) {
		if(y&1) res=res*x%mod;
		y>>=1; x=x*x%mod;
	}
	return res;
}
const int invG=fpow(G,mod-2);
void NTT(int *f,int n,bool fl=1) {
	static int tr[M];
	for(int i=0;i<n;i++) tr[i]=(tr[i>>1]>>1)|((i&1)?(n>>1):0);
	for(int i=0;i<n;i++) if(i<tr[i]) swap(f[i],f[tr[i]]);
	for(int p=2;p<=n;p<<=1) {
		int len=(p>>1),w=fpow(fl?G:invG,(mod-1)/p);
		for(int l=0;l<n;l+=p) {
			int buf=1;
			for(int i=l;i<l+len;i++) {
				int qwq=f[i+len]*buf%mod;
				f[i+len]=(f[i]-qwq)%mod;
				f[i]=(f[i]+qwq)%mod;
				buf=buf*w%mod;
			}
		}
	}
	if(fl) return ;
	int qwq=fpow(n,mod-2);
	for(int i=0;i<n;i++) f[i]=f[i]*qwq%mod; 
} 
int f[M],g[M],jie[N],djie[N],n;
int C(int n,int m) {
	if(m>n||n<0||m<0) return 0;
	return jie[n]*djie[m]%mod*djie[n-m]%mod;
}

inline int get(int a,int b) {
	return C(a+b-1,b); // (1,0) (a,b)
}

void solve() { 
//	memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
	n=rd(); 
	if(n==1) {
		printf("26 0"); return ;
	}
	n-=2;
	f[0]=fpow(26,n+2);
	for(int i=1;i<=n;i++) {
		int qwq=(i-1)*3+1,num=n+2-i*3; if(num<0) break ;
		int res=get(i+1,n-qwq);
		f[i]=res*fpow(26,num)%mod;
	}
	// 太屑了 不放 n^3 ,你玩nmd,是个紫就要 NTT 做差卷积??
	// 老子今天都不知道写几遍 NTT 了
	for(int i=0;i<=n;i++) f[i]=jie[i]*f[i]%mod;
	for(int i=0;i<=n;i++) g[i]=((i&1)?-1:1)*djie[i]%mod;
	reverse(f,f+1+n);
	int m; for(m=1;m<n+n+2;m<<=1);
	NTT(f,m,1); NTT(g,m,1);
	for(int i=0;i<m;i++) f[i]=f[i]*g[i]%mod;
	NTT(f,m,0);
	reverse(f,f+1+n);
	for(int i=0;i<=n;i++) {
		int qwq=f[i]*djie[i]%mod;
		qwq=(qwq%mod+mod)%mod;
		printf("%lld ",qwq);
	}
	printf("0 0"); 
}

signed main() {
	jie[0]=1;
	for(int i=1;i<=N-5;i++) jie[i]=jie[i-1]*i%mod;
	djie[N-5]=fpow(jie[N-5],mod-2);
	for(int i=N-5;i;i--) djie[i-1]=djie[i]*i%mod;
	solve();
	return 0;
} 

posted @ 2022-07-23 22:59  FxorG  阅读(51)  评论(0编辑  收藏  举报