Codeforces Round #641 Div1.F Slime and Sequences 中文题解
Slime and Sequences 中文题解
UPD:你可以在这里看到 Elegia 的题解:https://blog.csdn.net/EI_Captain/article/details/106122006
Easy Version
首先我们可以将长度为
设
求答案时,对每个
如果对每个
由于存在简单的
Hard Version
接下来考虑如何在低于
设
我们可以用一次多项式求逆求出
设
原式
由拉格朗日反演可得
我们可以在
总复杂度为
Problem and Tutorial by he_____he
Solution(Hard Version) by Elegia
Easy Version Code:
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template <typename T> bool chkmax(T &x,T y){return x<y?x=y,true:false;}
template <typename T> bool chkmin(T &x,T y){return x>y?x=y,true:false;}
int readint(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int cys=998244353;
int n;
ll fac[5005],inv[5005],d[5005][5005],ans[5005];
ll qpow(ll x,ll p){
ll ret=1;
for(;p;p>>=1,x=x*x%cys) if(p&1) ret=ret*x%cys;
return ret;
}
int main(){
n=readint();
d[0][0]=fac[0]=inv[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%cys;
inv[n]=qpow(fac[n],cys-2);
for(int i=n-1;i>=1;i--) inv[i]=inv[i+1]*(i+1)%cys;
for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) d[i][j]=(d[i-1][j-1]*(i-j+1)+d[i-1][j]*j)%cys;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ans[i]=(ans[i]+d[j][i]*inv[j])%cys;
for(int i=1;i<=n;i++) printf("%lld ",ans[i]*fac[n]%cys);
printf("\n");
return 0;
}
Hard Version Code:
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<ll> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template <typename T> bool chkmax(T &x,T y){return x<y?x=y,true:false;}
template <typename T> bool chkmin(T &x,T y){return x>y?x=y,true:false;}
int readint(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int cys=998244353,g=3,invg=(cys+1)/3;
int n;
ll ni[200015],fac[200015],inv[200015],tw[200005];
int mod(int x){return x>=cys?x-cys:x;}
ll qpow(ll x,ll p){
ll ret=1;
for(;p;p>>=1,x=x*x%cys) if(p&1) ret=ret*x%cys;
return ret;
}
vi operator+(vi a,vi b){
vi ret(max(a.size(),b.size()));
for(int i=0;i<ret.size();i++) ret[i]=mod((i<a.size()?a[i]:0)+(i<b.size()?b[i]:0));
return ret;
}
vi operator-(vi a,vi b){
vi ret(max(a.size(),b.size()));
for(int i=0;i<ret.size();i++) ret[i]=mod((i<a.size()?a[i]:0)+cys-(i<b.size()?b[i]:0));
return ret;
}
vi operator*(vi a,ll b){
for(int i=0;i<a.size();i++) a[i]=1ll*a[i]*b%cys;
return a;
}
vi operator>>(vi a,int b){
for(int i=0;i<a.size()-b;i++) a[i]=a[i+b];
a.resize(a.size()-b);
return a;
}
namespace poly{
int N,l;
int A[1100000],B[1100000],r[1100000],pre1[20][600000],pre2[20][600000];
void pre(){
for(int i=1,r=0;i<(1<<19);i<<=1,r++){
int w=1,wn=qpow(g,(cys-1)/(i<<1));
for(int j=0;j<i;j++,w=1ll*w*wn%cys) pre1[r][j]=w;
}
for(int i=1,r=0;i<(1<<19);i<<=1,r++){
int w=1,wn=qpow(invg,(cys-1)/(i<<1));
for(int j=0;j<i;j++,w=1ll*w*wn%cys) pre2[r][j]=w;
}
}
void ntt(int *A,int N,int f){
for(int i=0;i<N;i++) if(i<r[i]) swap(A[i],A[r[i]]);
for(int i=1,r=0;i<N;i<<=1,r++){
for(int j=0;j<N;j+=(i<<1)){
for(int k=j;k<j+i;k++){
int x=A[k],y=1ll*A[k+i]*(f>0?pre1[r][k-j]:pre2[r][k-j])%cys;
A[k]=mod(x+y); A[k+i]=mod(x+cys-y);
}
}
}
if(f<0){
int invn=qpow(N,cys-2);
for(int i=0;i<N;i++) A[i]=1ll*A[i]*invn%cys;
}
}
void init(int t){
N=1,l=0;
for(;N<t;N<<=1) l++;
for(int i=0;i<N;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
void getmul(){
ntt(A,N,1); ntt(B,N,1);
for(int i=0;i<N;i++) A[i]=1ll*A[i]*B[i]%cys;
ntt(A,N,-1);
}
vi mul(vi a,vi b){
init(a.size()+b.size());
for(int i=0;i<N;i++) A[i]=i<a.size()?a[i]:0;
for(int i=0;i<N;i++) B[i]=i<b.size()?b[i]:0;
getmul();
vi ret(a.size()+b.size()-1);
for(int i=0;i<ret.size();i++) ret[i]=A[i];
return ret;
}
vi polyinv(vi a,int l){
if(l==1) return vi(1,qpow(a[0],cys-2));
a.resize(l);
vi b=polyinv(a,(l+1)/2);
init(l<<1);
for(int i=0;i<N;i++) A[i]=i<l?a[i]:0;
for(int i=0;i<N;i++) B[i]=i<(l+1)/2?b[i]:0;
ntt(A,N,1); ntt(B,N,1);
for(int i=0;i<N;i++) A[i]=1ll*A[i]*B[i]%cys*B[i]%cys;
ntt(A,N,-1);
vi t=b*2;
t.resize(l);
for(int i=0;i<l;i++) t[i]=mod(t[i]+cys-A[i]);
return t;
}
vi polydiff(vi a){
for(int i=0;i<a.size()-1;i++) a[i]=1ll*(i+1)*a[i+1]%cys;
a.resize(a.size()-1);
return a;
}
vi polyint(vi a){
a.resize(a.size()+1);
for(int i=a.size()-1;i>=1;i--) a[i]=1ll*a[i-1]*ni[i]%cys;
a[0]=0;
return a;
}
vi polyln(vi a,int l){
return polyint(mul(polydiff(a),polyinv(a,l)));
}
vi polyexp(vi a,int l){
if(l==1) return vi(1,1);
a.resize(l);
vi b=polyexp(a,(l+1)/2);
init(l<<1);
vi t=mul(b,vi(1,1)-polyln(b,l)+a);
t.resize(l);
return t;
}
vi polypow(vi a,int l,int k){
return polyexp(polyln(a,l)*k,l);
}
}
vi getans(){
vi f(0);
for(int i=0;i<=n+1;i++) f.push_back(inv[i+1]);
vi tmp=poly::mul(f,poly::polyinv((vi(1,1)-f)>>1,n+1));
vi tw(0); tw.resize(n);
for(int i=0;i<n;i++) tw[i]=tmp[i+1];
vi h(0);
h.push_back(1),h.push_back(1);
h=poly::polyinv(poly::polyln(h,n+3)>>1,n+2);
vi g=poly::polyinv((vi(1,1)-h)>>1,n+1);
vi ph=poly::polypow(h,n+1,n+1);
vi t1=poly::mul(g,ph);
vi tmp1=poly::mul(poly::polydiff(h),ph);
tmp1.resize(n+1);
vi tmp2=poly::mul(g,g);
tmp2.resize(n+1);
vi t2=poly::mul(tmp1,tmp2);
for(int i=0;i<n;i++) tw[i]=mod(tw[i]+cys-ni[n+1]*mod(t1[i+1]*(n-i+1)%cys+t2[i+1])%cys);
for(int i=0;i<n;i++) tw[i]=tw[i]*fac[i]%cys;
reverse(tw.begin(),tw.end());
tmp.clear();
for(int i=0;i<n;i++) tmp.push_back(i&1?cys-inv[i]:inv[i]);
tw=poly::mul(tw,tmp);
tw.resize(n);
reverse(tw.begin(),tw.end());
return tw;
}
int main(){
poly::pre();
n=readint();
fac[0]=inv[0]=1;
for(int i=1;i<=n+5;i++) fac[i]=fac[i-1]*i%cys;
inv[n+5]=qpow(fac[n+5],cys-2);
for(int i=n+4;i>=1;i--) inv[i]=inv[i+1]*(i+1)%cys;
for(int i=1;i<=n+5;i++) ni[i]=inv[i]*fac[i-1]%cys;
vi res=getans();
for(int i=0;i<n;i++) printf("%lld ",res[i]*fac[n]%cys*inv[i]%cys);
printf("\n");
return 0;
}