"蔚来杯"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;
}