【LuoguP7439】[KrOI2021]Feux Follets 弱化版

【LuoguP7439】[KrOI2021]Feux Follets 弱化版

by AmanoKumiko

Description

\(cyc_\pi\)表示将长度为\(n\)的排列\(\pi\)当成置换时能分解的循环置换个数。给定\(n,k\)和一个\(k-1\)次多项式\(F(x)\)

求:

\[\sum_{\pi}F(cyc_{\pi}) \]

其中\(\pi\)是长度为\(n\)的错排列

\(998244353\)取模

Input

一行两个整数\(n,k\)

第二行\(k\)个整数读入\(F(x)\)

Output

一行一个整数表示答案

Sample Input

6 4
11 43 27 7

Sample Output

53070

Data Constraint

\(1\le n,k\le 10^5\)

Solution

一个长度\(\ge2\)的环\(EGF\)\(G(x)=\sum_{i\ge2}\frac{x^i}{i}=-\ln(1-x)-x\)

那么我们要求的就是\(\sum_{i=0}^{+\infty}\frac{G^i(x)}{i}[x^n]n!F(i)\)

Sol1

考虑加入一元分离信息,直接求出每个次幂的答案,最后多点求值

\(H(x)=\sum_{i=0}^{+\infty}u^iG^i(x)=\frac{1}{1-uG}\)

由于\(G(x)\)的最低次数为\(2\),故复合逆不存在

考虑设\(\frac{g^2}{2}=-\ln(1-x)-x\)

\(g=\sqrt{-2\ln(1-x)-2x}\)

显然复合逆存在,设为\(f\)

那么

\[\begin{align} [x^n]H(x)&=\frac{1}{n}[x^{n-1}]\frac{ux}{(1-\frac{ux^2}{2})^2}(\frac{f}{x})^{-n}\\ &=\frac{1}{n}[x^{n-1}]ux\sum_{i=0}^{+\infty}(i+1)(\frac{ux^2}{2})^i(\frac{f}{x})^{-n}\\ [x^nu^k]&=\frac{k}{n2^{k-1}}[x^{n-2k}](\frac{f}{x})^{-n} \end{align} \]

Sol2

其实两种方法都要多点求值

由于次幂的存在,考虑把多项式转成牛顿级数,令其为\(F^*(x)\)

那么有

\[\begin{align} \sum_{i=0}^{+\infty}\frac{G^i(x)}{i}[x^n]n!F(i)&=\sum_{i=0}^{+\infty}\frac{G^i(x)}{i}[x^n]n!\sum_{j=0}^{k-1}f_j^*\binom{i}{j}\\ &=\sum_{j=0}^{k-1}f_j^*[y^j]e^{(1+y)(-\ln(1-x)-x)} \end{align} \]

这里用组合意义,加入辅助因子变形

我们先处理\(e^{y(-\ln(1-x)-x)}\),最后多项式平移弄回去

到这里就和上面差不多了,直接快进一下

\[[x^ny^k]e^{\frac{yg^2(x)}{2}}=\frac{1}{n2^{k-1}(k-1)!}[x^{n-2k}](\frac{f}{x})^{-n} \]

由于一些项系数可能为\(0\),在牛顿迭代里面有亿些偏移的细节

最后给出我的卡着\(1.50s\)过的垃圾代码

Code

#include<bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 600010
#define mo 998244353
#define LL long long
#define ULL unsigned long long

namespace IO{
	const int sz=1<<22;
	char a[sz+5],b[sz+5],*p1=a,*p2=a,*t=b,p[105];
	inline char gc(){
		return p1==p2?(p2=(p1=a)+fread(a,1,sz,stdin),p1==p2?EOF:*p1++):*p1++;
	}
	template<class T>void read(T&x){
		x=0;char c=gc();
		for(;c<'0'||c>'9';c=gc());
		for(;c>='0'&&c<='9';c=gc())x=x*10+(c-'0');
	}
	inline void flush(){fwrite(b,1,t-b,stdout),t=b;}
	inline void pc(char x){*t++=x;if(t-b==sz)flush();}
	template<class T>void write(T x,char c='\n'){
		if(x==0)pc('0');int t=0;
		for(;x;x/=10)p[++t]=x%10+'0';
		for(;t;--t)pc(p[t]);pc(c);
	}
	struct F{~F(){flush();}}f;
}
using IO::read;
using IO::write;

int rev[N],G1[N],G2[N],fac[N],ifac[N],inv[N];

inline int getlen(int x){return 1<<32-__builtin_clz(x);}

inline int mod(int x){return x>=mo?x-mo:x;}

inline int mi(int x,int y){
	if(!y)return 1;
	if(y==1)return x;
	return y%2?1ll*x*mi(1ll*x*x%mo,y/2)%mo:mi(1ll*x*x%mo,y/2);
}

void init(){
	fac[0]=ifac[0]=1;
	fo(i,1,N-10)fac[i]=1ll*fac[i-1]*i%mo,inv[i]=(i==1?1:1ll*mo/i*mod(mo-1ll*inv[mo%i]%mo)%mo);
	ifac[N-10]=mi(fac[N-10],mo-2);
	fd(i,N-11,1)ifac[i]=1ll*ifac[i+1]*(i+1)%mo;
	for(int l=1;l<=N-10;l<<=1)G1[l]=mi(3,(mo-1)/(l*2)),G2[l]=mi(G1[l],mo-2);
}

inline void BRT(int x){fo(i,0,x-1)rev[i]=(rev[i>>1]>>1)|((i&1)?(x>>1):0);}

struct poly{
	vector<int>val;
	inline poly(int x=0){if(x)val.push_back(x);}
	inline poly(const vector<int>&x){val=x;}
	inline void Rev(){reverse(val.begin(),val.end());}
	inline void ins(int x){val.push_back(x);}
	inline void clear(){vector<int>().swap(val);}
	inline int sz(){return val.size();}
	inline void rsz(int x){val.resize(x);}
	inline void shrink(){for(;sz()&&!val.back();val.pop_back());}
	inline poly modxn(int x){
		if(val.size()<=x)return poly(val);
		else return poly(vector<int>(val.begin(),val.begin()+x));
	}
	inline int operator[](int x)const{
		if(x<0||x>=val.size())return 0;
		return val[x];
	}
	inline void NTT(int x){
		static ULL f[N],w[N];
		w[0]=1;
		fo(i,0,sz()-1)f[i]=(((LL)mo<<5)+val[rev[i]])%mo;
		for(int mid=1;mid<sz();mid<<=1){
			int tmp=(x==1?G1[mid]:G2[mid]);
			fo(i,1,mid-1)w[i]=w[i-1]*tmp%mo;
			for(int i=0;i<sz();i+=(mid<<1)){
				fo(j,0,mid-1){
					int t=w[j]*f[i|j|mid]%mo;
					f[i|j|mid]=f[i|j]+mo-t;f[i|j]+=t;
				}
			}
		}
		if(x==-1){int tmp=inv[sz()];fo(i,0,sz()-1)val[i]=f[i]%mo*tmp%mo;}
		else{fo(i,0,sz()-1)val[i]=f[i]%mo;}
	}
	inline void DFT(){NTT(1);}
	inline void IDFT(){NTT(-1);}
	inline friend poly operator*(poly x,poly y){
		if(x.sz()<30||y.sz()<30){
			if(x.sz()>y.sz())swap(x,y);
			poly ret;
			ret.rsz(x.sz()+y.sz());
			fo(i,0,ret.sz()-1){
				for(int j=0;j<=i&&j<x.sz();j++)
					ret.val[i]=mod(ret.val[i]+1ll*x[j]*y[i-j]%mo);
			}
			return ret;
		}
		int l=getlen(x.sz()+y.sz()-2);
		x.rsz(l);y.rsz(l);BRT(l);
		x.DFT();y.DFT();
		fo(i,0,l-1)x.val[i]=1ll*x[i]*y[i]%mo;
		x.IDFT();
		return x;
	}
	inline friend poly operator+(poly x,poly y){
		poly ret;
		ret.rsz(max(x.sz(),y.sz()));
		fo(i,0,ret.sz()-1)ret.val[i]=mod(x[i]+y[i]);
		return ret;
	}
	inline friend poly operator-(poly x,poly y){
		poly ret;
		ret.rsz(max(x.sz(),y.sz()));
		fo(i,0,ret.sz()-1)ret.val[i]=mod(x[i]-y[i]+mo);
		return ret;
	}
	inline poly &operator*=(poly x){return (*this)=(*this)*x;}
	inline poly &operator+=(poly x){return (*this)=(*this)+x;}
	inline poly &operator-=(poly x){return (*this)=(*this)-x;}
	inline poly deriv(){
		poly f;
		f.rsz(sz()-1);
		fo(i,0,sz()-2)f.val[i]=1ll*(i+1)*val[i+1]%mo;
		return f;
	}
	inline poly integ(){
		poly f;
		f.rsz(sz()+1);
		fo(i,1,sz())f.val[i]=1ll*val[i-1]*inv[i]%mo;
		return f;
	}
	inline poly inver(int Len){
		poly f,g;
		f.clear();g.clear();
		g.ins(mi(val[0],mo-2));
		for(int i=1;i<Len*2;i<<=1){
			int Len=i<<1;
			f.rsz(Len);
			g.rsz(Len);
			BRT(Len);
			fo(j,0,i-1)f.val[j]=(j<val.size()?val[j]:0);
			f.DFT();g.DFT();
			fo(j,0,Len-1)g.val[j]=1ll*g[j]*mod(mo+2-1ll*f[j]*g[j]%mo)%mo;
			g.IDFT();
			g.rsz(i);
		}
		return g.modxn(Len);
	}
	inline poly Sqrt(int Len){
		int i2=inv[2];
		poly f,g,tmp;
		f.clear();g.clear();
		g.ins(1);
		for(int i=1;i<Len*2;i<<=1){
			int Len=i<<1;
			f.rsz(Len);
			tmp=g.inver(i);
			tmp.rsz(Len);
			BRT(Len);
			fo(j,0,i-1)f.val[j]=(j<val.size()?val[j]:0);
			f.DFT();tmp.DFT();
			fo(j,0,Len-1)f.val[j]=1ll*f[j]*tmp[j]%mo;
			f.IDFT();
			g.rsz(i);
			fo(j,0,i-1)g.val[j]=1ll*i2*mod(g[j]+f[j])%mo;
		}
		return g.modxn(Len);
	}
	inline poly Ln(int Len){
		return (deriv()*inver(Len)).integ().modxn(Len);
	}
	inline poly Exp(int Len){
		poly f;
		f.clear();
		f.ins(1);
		for(int i=2;i<Len*2;i<<=1)f=(f*(1-f.Ln(i)+modxn(i))).modxn(i);
		return f.modxn(Len);
	}
	inline poly Pow(int Len,int k){
		poly f;
		f.clear();
		int tail=0;
		while(val[tail]==0&&tail<sz())tail++;
		if(tail>=sz())return f;
		if(tail*k>=Len)return f;
		f.rsz(Len);
		int Mul=mi(val[tail],mo-2);
		fo(i,0,min(Len-1,sz()-tail-1))f.val[i]=1ll*val[i+tail]*Mul%mo;
		Mul=mi(val[tail],k);
		f=f.Ln(Len);
		fo(i,0,Len-1)f.val[i]=1ll*f[i]*(k%mo)%mo;
		f=f.Exp(Len);
		fd(i,Len-1,tail*k)f.val[i]=1ll*f[i-tail*k]*Mul%mo;
		fo(i,0,tail*k-1)f.val[i]=0;
		return f;
	}
};

struct Evaluation{
	#define ls x<<1
	#define rs (x<<1)|1
	poly f,g[N],h[N];
	int b[N];
	void solve1(int x,int l,int r){
		if(l==r){g[x].rsz(2);g[x].val[0]=1;g[x].val[1]=mod(mo-l);return;}
		int mid=l+r>>1,Len=1;
		solve1(ls,l,mid);solve1(rs,mid+1,r);
		while(Len<r-l+1+1)Len<<=1;BRT(Len);
		poly A=g[ls],B=g[rs];
		A.rsz(Len);B.rsz(Len);
		A.DFT();B.DFT();
		fo(i,0,Len-1)A.val[i]=1ll*A[i]*B[i]%mo;
		A.IDFT();
		g[x]=A.modxn(r-l+2);
	}
	void solve2(int x,int l,int r){
		if(l==r){b[l]=h[x][0];return;}
		int mid=l+r>>1,Len=1;
		while(Len<(r-l+1<<1)+1)Len<<=1;BRT(Len);
		g[ls].Rev();g[rs].Rev();
		g[ls].rsz(Len);g[rs].rsz(Len);h[x].rsz(Len);
		g[ls].DFT();g[rs].DFT();h[x].DFT();
		fo(i,0,Len-1)g[ls].val[i]=1ll*g[ls][i]*h[x][i]%mo;
		fo(i,0,Len-1)g[rs].val[i]=1ll*g[rs][i]*h[x][i]%mo;
		g[ls].IDFT();g[rs].IDFT();
		h[ls].rsz(mid-l+1+1);
		fo(i,0,mid-l+1)h[ls].val[i]=g[rs][i+r-mid];
		h[rs].rsz(r-mid+1);
		fo(i,0,r-mid)h[rs].val[i]=g[ls][i+mid-l+1];
		solve2(ls,l,mid);solve2(rs,mid+1,r);
	}
	void get(){
		int n=f.sz()-1,m=n+1;
		solve1(1,0,n);
		g[1]=g[1].inver(n+1);
		g[1].Rev();
		int Len=1;
		while(Len<(n<<1)+1)Len<<=1;BRT(Len);
		g[1].rsz(Len);f.rsz(Len);
		g[1].DFT();f.DFT();
		fo(i,0,Len-1)g[1].val[i]=1ll*g[1][i]*f[i]%mo;
		g[1].IDFT();
		h[1].rsz(n+1);
		fo(i,0,n)h[1].val[i]=g[1][i+n];
		solve2(1,0,n);
	}
}t;

inline poly Newton(int Len){
	poly f,res;
	f.ins(0);f.ins(1);
	for(int i=2;i<Len;){
		i<<=1;
		poly tmp=1-f;tmp.rsz(i);
		poly _Ln=(tmp.Ln(i+1)*(mo-2)-(2*f)).modxn(i+1);
		poly _Sqrt;_Sqrt.clear();
		fo(j,0,i-2)_Sqrt.ins(_Ln[j+2]);
		_Sqrt=_Sqrt.Sqrt(i-1);
		_Sqrt.rsz(i);
		fd(j,i-1,1)_Sqrt.val[j]=_Sqrt[j-1];
		_Sqrt.val[0]=0;
		fo(j,0,i-1)_Ln.val[j]=_Ln[j+1];
		_Ln.val.pop_back();
		_Ln-=_Sqrt;
		_Ln=(_Ln*tmp).modxn(i+1);
		poly _inv;_inv.clear();
		fo(j,0,i-1)_inv.ins(f[j+1]);
		_Ln=(_inv.inver(i)*_Ln).modxn(i);
		f.rsz(i);
		f-=_Ln;
	}
	return f.modxn(Len);
}

poly f,g,h,fc;

int n,k,ans,st[N];

int main(){
	init();
	read(n);read(k);
	fo(i,0,k-1){
		int x;
		read(x);
		f.ins(x);
	}
	t.f=f;
	t.get();
	poly A,B;
	fo(i,0,k-1)A.ins(1ll*t.b[i]*ifac[i]%mo);
	fo(i,0,k-1)B.ins((i&1)?mo-ifac[i]:ifac[i]);
	A*=B;
	f=A.modxn(k);
	fo(i,0,k-1)f.val[i]=1ll*f[i]*fac[i]%mo;
	g=Newton(n+2);
	fo(i,0,n)g.val[i]=g[i+1];
	g.val.pop_back();
	g=g.inver(n+1);
	g=g.Pow(n+1,n);
	h.rsz(k);
	h.val[0]=0;
	int tmp=1,i2=inv[2];
	fo(i,1,k-1){
		h.val[i]=1ll*tmp*i%mo*fac[n-1]%mo*g[n-2*i]%mo;
		tmp=1ll*tmp*i2%mo;
	}
	h.Rev();
	fo(i,0,k-1)fc.ins(ifac[i]);
	fc=(fc*h).modxn(k);
	fc.Rev();
	fo(i,0,k-1)ans=mod(ans+1ll*f[i]*fc[i]%mo*ifac[i]%mo);
	printf("%d",ans);
	return 0;
}
posted @ 2022-03-31 22:07  冰雾  阅读(81)  评论(0编辑  收藏  举报