题意为 定义 $$F_{n,k}$$ 为长度为n的字符串中出现k个bit的字符串数量
让我们求 $$F_{n,0},F_{n,1}.....F_{n,n}$$
首先我们想等于k个bit的数量不是很好想
如果我们能想出大于等于k的表达式,在进行容斥或反演,会简单一些
假设我们想求长度为n的字符串中大于等于k个bit的数量
我们可以利用组合数学的捆绑法----把k个bit捆绑在一起,这样一共有 n-3*k+k个位置
我们从中选出k个来放bit,剩下n-3*k个位置放任意字符,等于
记做 f(k)
则f(k)由恰好出现k次,k+1次....n次累加起来,在乘上组合系数,有
这里特别解释一下为什么要乘上组合系数,因为我们之前计算f(k)的时候,假设我们计算的是
n=6,k=1,那么我们在计算bit***这个字符串的时候,实际上已经计算了一次bitbit
而我们计算***bit的时候,又算了一边bitbit,所以实际上我们算的f(k)是有重复的
而这个重复的影响就是这个组合系数
好我们得到这个式子时候,对他进行二项式反演(容斥),把它变成
接下来继续推倒,把组合数展开,可以得到
接下来令
有
接下来我们只需要令右边i等于i+k
有
我们知道卷积是
而上面n-k-i正好加上i+k等于n
所以考虑翻转G(i)
之后卷一卷
感谢凌乱之风的博客-CSDN博客让我搞懂了这道题
代码如下
#include <bits/stdc++.h>
#include <iomanip>
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
#define int long long
#define len(x) ((int)x.size())
#define pb push_back
#define pll pair<int,int>
#define ld double
#define x first
#define y second
using namespace std;
const int N=2e6+10;
int mod=998244353;
int n;
inline int add(int x, int y) {
x += y;
if(x >= mod) x -= mod;
return x;
}
inline int sub(int x, int y) {
x -= y;
if(x < 0) x += mod;
return x;
}
inline int mul(int x, int y) {
return 1ll * x * y % mod;
}
inline int qpow(int x, int y) {
int ret = 1;
for(; y; y >>= 1, x = mul(x, x)) if(y & 1) ret = mul(ret, x);
return ret;
}
const int G = 3;
const int Ginv = qpow(G, mod - 2);
int rev[N<<1];
inline void ntt(int *a, int n, int o) {
for(int i = 0; i < n; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * (n >> 1));
for(int i = 0; i < n; i ++) if(rev[i] > i) swap(a[i], a[rev[i]]);
for(int len = 2; len <= n; len <<= 1) {
int w0 = qpow((o == 1)? G : Ginv, (mod - 1) / len);
for(int j = 0; j < n; j += len) {
int wn = 1;
for(int k = j; k < j + (len >> 1); k ++, wn = mul(wn, w0)) {
int X = a[k], Y = mul(a[k + (len >> 1)], wn);
a[k] = add(X, Y), a[k + (len >> 1)] = sub(X, Y);
}
}
}
int ninv = qpow(n, mod - 2);
if(o == -1)
for(int i = 0; i < n; i ++) a[i] = mul(a[i], ninv);
}
#define clr(a, n) (memset(a, 0, sizeof(int) * n))
int aa[N << 1], bb[N << 1], lim=362144*4;
inline vector<int> operator * (const vector<int> & A, const vector<int> & B) {
for(int i = 0; i < len(A); i ++) aa[i] = A[i];
for(int i = 0; i < len(B); i ++) bb[i] = B[i];
vector<int> C;
C.resize(min(lim, len(A) + len(B) - 1));
int len = 1;
for(; len <= len(A) + len(B) - 1; len <<= 1);
ntt(aa, len, 1), ntt(bb, len, 1);
for(int i = 0; i < len; i ++) aa[i] = mul(aa[i], bb[i]);
ntt(aa, len, -1);
for(int i = 0; i < len(C); i ++) C[i] = aa[i];
clr(aa, len), clr(bb, len);
return C;
}
template <typename _Tp>void input(_Tp &x){
char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
if(f)x=-x;
}
template <typename _Tp,typename... Args>void input(_Tp &t,Args &...args){input(t);input(args...);}
int fc[N],gc[N];
void init()
{
fc[0]=1;
for(int i=1;i<=n;i++) fc[i]=fc[i-1]*i%mod;
gc[n]=qpow(fc[n],mod-2);
for(int i=n-1;i>=0;i--) gc[i]=gc[i+1]*(i+1)%mod;
}
int C(int n,int m)
{
return fc[n]*gc[m]%mod*gc[n-m]%mod;
}
int f(int k){
int res=C(n-2*k,k)*qpow(26,n-3*k);
return res%mod;
}
int F(int k){
return (f(k)*fc[k])%mod;
}
int Gi(int k){
return (qpow(mod-1,k)*gc[k])%mod;
}
vector<int> ff,gg;
signed main()
{
cin>>n;
init();
fer(i,0,n){
if(n>=3*i){
ff.pb(F(i));
}
else{
ff.pb(0);
}
}
fer(i,0,n){
gg.pb(Gi(i));
}
reverse(gg.begin(),gg.end());
vector<int> res;
res=ff*gg;
res.resize(n*2+1);
fer(i,0,n){
cout<<(res[i+n]*gc[i])%mod<<' ';
}
cout<<"\n";
}