【CF923E】Perpetual Subtraction

【CF923E】Perpetual Subtraction

by AmanoKumiko

Description

有一个整数x,范围在[0,n]之间

初值为i的概率为pi

然后会有m次操作

每次x会等概率变成[0,x]中的整数

对于每个i[0,n],求出m次操作后xi的概率

998244353取模

Input

第一行两个数n,m

第二行n+1个数读入p

Output

一行一个数表示答案

Sample Input

9 350
3 31 314 3141 31415 314159 3141592 31415926 314159265 649178508

Sample Output

822986014 12998613 84959018 728107923 939229297 935516344 27254497 413831286 583600448 442738326

Data Constraint

1n105,1m1018

Solution

需要对积分比较敏感呢

fi,j表示i次操作后xj的概率

那么有

fi,j=k=jnfi1,kk+1

用生成函数观察性质

(1)Fi(x)=j=0nfi,jxj(2)=j=0nxjk=jnfi1,kk+1(3)=k=0nfi1,kk+1j=0kxj(4)=k=0nfi1,kk+1xk+11x1(5)=1x1k=0nfi1,k1xtkdt(6)=1x11xFi1(t)dt

这里从1开始积分不好处理

我们希望的是0xf(t)dt=f(x)dx

那么设Gi(x)=Fi(x+1)同时Gi(x)=j=0ngi,jxj

(7)Gi(x)=1x0xFi1(t+1)d(t+1)(8)=k=0ngi1,kxkk+1

所以gi,j=gi1,jj+1
gm,j=g0,j(j+1)m

众所周知,多项式平移可以用二项式定理展开变为卷积

(9)G0(x)=F0(x+1)(10)=i=0npi(x+1)i(11)=i=0npij=0i(ij)xj(12)=j=0nxjj!i=jni!pi(ij)!

(13)Fm(x)=Gm(x1)(14)=i=0ngm,i(x1)i(15)=i=0ngm,ij=0i(ij)xj(1)ij(16)=j=0nxjj!i=jngm,ii!(1)ij(ij)!

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 500010
#define mo 998244353
#define LL long long

vector<int>Is;

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

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

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(){
	Is.push_back(1);
	fac[0]=ifac[0]=1;
	F(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);
}

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

struct poly{
	vector<int>val;
	void ins(int x){val.push_back(x);}
	void clear(){vector<int>().swap(val);}
	int sz(){return val.size();}
	void rsz(int x){val.resize(x);}
	void shrink(){for(;sz()&&!val.back();val.pop_back());}
	poly modxn(int x){
		if(val.size()<=x)return (poly){val};
		else return (poly){vector<int>(val.begin(),val.begin()+x)};
	}
	poly I(){return (poly){Is};}
	int operator[](int x)const{
		if(x<0||x>=val.size())return 0;
		return val[x];
	}
	void NTT(int x){
		F(i,0,sz()-1)if(rev[i]<i)swap(val[rev[i]],val[i]);
		for(int mid=1;mid<sz();mid<<=1){
			for(int i=0,gn=1;i<sz();i+=(mid<<1),gn=1){
				F(j,0,mid-1){
					int le=val[i+j],ri=1ll*gn*val[i+j+mid]%mo;
					val[i+j]=mod(le+ri);val[i+j+mid]=mod(le-ri+mo);
					gn=1ll*gn*(x==1?G1[mid]:G2[mid])%mo;
				}
			}
		}
		if(x==-1){F(i,0,sz()-1)val[i]=1ll*val[i]*inv[sz()]%mo;}
	}
	void DFT(){NTT(1);}
	void IDFT(){NTT(-1);}
	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());
			F(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);
			}
	//		ret.shrink();
			return ret;
		}
		int l=1;
		while(l<x.sz()+y.sz()-1)l<<=1;
		x.rsz(l);y.rsz(l);BRT(l);
		x.DFT();y.DFT();
		F(i,0,l-1)x.val[i]=1ll*x[i]*y[i]%mo;
		x.IDFT();
	//	x.shrink();
		return x;
	}
	friend poly operator+(poly x,poly y){
		poly ret;
		ret.rsz(max(x.sz(),y.sz()));
		F(i,0,ret.sz()-1)ret.val[i]=mod(x[i]+y[i]);
		return ret;
	}
	friend poly operator-(poly x,poly y){
		poly ret;
		ret.rsz(max(x.sz(),y.sz()));
		F(i,0,ret.sz()-1)ret.val[i]=mod(x[i]-y[i]+mo);
		return ret;
	}
	poly &operator*=(poly x){return (*this)=(*this)*x;}
	poly &operator+=(poly x){return (*this)=(*this)+x;}
	poly &operator-=(poly x){return (*this)=(*this)-x;}
	poly deriv(){
		poly f;
		f.rsz(sz()-1);
		F(i,0,sz()-2)f.val[i]=1ll*(i+1)*val[i+1]%mo;
		return f;
	}
	poly integ(){
		poly f;
		f.rsz(sz()+1);
		F(i,1,sz())f.val[i]=1ll*val[i-1]*inv[i]%mo;
		return f;
	}
	poly inver(int Len){
		poly f,g;
		f.clear();g.clear();
		g.val.push_back(mi(val[0],mo-2));
		for(int i=2;i<Len*2;i<<=1){
			f.rsz(i<<1);
			g.rsz(i<<1);
			BRT(i<<1);
			F(j,0,i-1)f.val[j]=(j<val.size()?val[j]:0);
			f.DFT();g.DFT();
			F(j,0,(i<<1)-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);
	}
	poly Ln(int Len){
		return (deriv()*inver(Len)).integ().modxn(Len);
	}
	poly Exp(int Len){
		poly f;
		f.clear();
		f.val.push_back(1);
		for(int i=2;i<Len*2;i<<=1)f=(f*(I()-f.Ln(i)+modxn(i))).modxn(i);
		return f.modxn(Len);
	}
	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);
		F(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);
		F(i,0,Len-1)f.val[i]=1ll*f[i]*k%mo;
		f=f.Exp(Len);
		Fd(i,Len-1,tail*k)f.val[i]=1ll*f[i-tail*k]*Mul%mo;
		F(i,0,tail*k-1)f.val[i]=0;
		return f;
	}
};

int n,p[N];
LL m;

int main(){
	init();
	scanf("%d%lld",&n,&m);
	F(i,0,n)scanf("%d",&p[i]);
	poly f,g,G0,Fm;
	F(i,0,n)f.ins(ifac[i]);
	F(i,0,n)g.ins(1ll*p[n-i]*fac[n-i]%mo);
	f*=g;G0.rsz(n+1);
	F(i,0,n)G0.val[i]=1ll*f[n-i]*ifac[i]%mo*mi(mi(i+1,m%(mo-1)),mo-2)%mo;
	f.clear();g.clear();
	F(i,0,n)f.ins((i&1)?mo-ifac[i]:ifac[i]);
	F(i,0,n)g.ins(1ll*G0[n-i]*fac[n-i]%mo);
	f*=g;Fm.rsz(n+1);
	F(i,0,n)Fm.val[i]=1ll*f[n-i]*ifac[i]%mo;
	F(i,0,n)printf("%d ",Fm[i]);
	return 0;
}
posted @   冰雾  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示