记录编号 362410 评测结果 AAAAAAWWWW
题目名称 [HZOI 2015] 帕秋莉的超级多项式 最终得分 60
用户昵称 GravatarYGOI_真神名曰驴蛋蛋 是否通过 未通过
代码语言 C++ 运行时间 33.244 s
提交时间 2017-01-07 10:44:48 内存使用 9.29 MiB
显示代码纯文本
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <algorithm>
typedef int TYPE;
const int MAXN=262144+10;
inline TYPE input() {
	static int c;static TYPE k;k=0;
	do c=getchar(); while(c<'0'||c>'9');
	do k=k*10+c-'0',c=getchar(); while(c>='0'&&c<='9');
	return k;
}
inline TYPE print(const TYPE&k,const char&end=' ') {
	return printf("%d%c",k,end);
}
inline TYPE print(const TYPE*a,const int&N,const char&step=' ',const char&end='\n') {
	for(int i=0;i<N;printf("%d%c",a[i++],step));
	return printf("%c",end);
}
namespace Number_Theory {
	const TYPE mod=998244353;
	const TYPE god=3;
	TYPE pow(TYPE a,TYPE b) {
		TYPE ans=1;
		for(ans=1;b;b>>=1ll,a=1ll*a*a%mod)
			if(b&1)ans=1ll*ans*a%mod;
		return ans;
	}
 
 
 
	void rotate(TYPE*a,int N) {
		for(int i=1,j=0;i<N;++i) {
			int k=N;
			do {k>>=1;j^=k;}while(j<k);
			if(i<j)std::swap(a[i],a[j]);
		}
	}
	int SPFA=0;
	void NTT(TYPE *a,int N,const int&is=1) {
		SPFA+=N;
		rotate(a,N);
		for(int m=2;m<=N;m<<=1) {
			const int mh=m>>1;
			const TYPE wn=pow(god,is==1?mod-1-(mod-1)/m:(mod-1)/m);
			for(int r=0;r<N;r+=m) {
				TYPE w=1;
				TYPE *b=a+r;
				TYPE *c=a+r+mh;
				for(int k=0;k<mh;++k) {
					const unsigned int u=b[k];
					const TYPE v=1ll*c[k]*w%mod;
					b[k]=(u+v+mod)%mod;
					c[k]=(u-v+mod)%mod;
					w=1ll*w*wn%mod;
				}
			}
		}
		if(is<0) {
			const TYPE inv=pow(N,mod-2);
			for(int i=0;i<N;++i) 
				a[i]=1ll*a[i]*inv%mod;
		}
	}
 
 
 
	//calc 1/a(x)
	//
	//
	//		g(x)*f(x)                =   1 (mod x^n)
	//		g(x)*f(x)-1              =   0 (mod x^n)
	//		(g(x)*f(x)-1)^2          =   0 (mod x^2n)
	//		g^2(x)f^2(x)-2g(x)f(x)+1 =   0 (mod x^2n)
	//		2g(x)f(x)-g^2(x)f^2(x)   =   1 (mod x^2n)
	//		(2g(x)-g^2(x)*f(x))*f(x) =   1 (mod x^2n)
	//		
	//			new g(x) = 2g(x)-g^2(x)*f(x)
	//		
	void inv(TYPE *a,TYPE*b,int N) {
		static TYPE c[MAXN];
		if(N==1) {
			b[0]=pow(a[0],mod-2);
			return ;
		}inv(a,b,N>>1);
		const int mh=N<<1;
		memcpy(c,a,sizeof(TYPE)*N);
		memset(c+N,0,sizeof(TYPE)*N);
		//print(mh);
		//printf("\n>>>");print(b,mh);
		//printf(">>>");print(c,mh);
		NTT(b,mh,1);NTT(c,mh,1);
 
		for(int i=0;i<mh;++i) {
			b[i]=1ll*(2ll-1ll*b[i]*c[i]%mod+mod)%mod*b[i]%mod;
		}//print(N);print(b,N);
		NTT(b,mh,-1);
		memset(b+N,0,sizeof(TYPE)*N);
		//print(N);print(b,N);
	}
 
 
 
	//calc sqrt(a(x))
	//		
	//		
	//		g^2(x) = f(x) (mod x^n)
	//		g^2(x)-f(x) = 0 (mod x^n)
	//		(g^2(x)-f(x))^2=0 (mod x^2n)
	//		(g^2(x)+f(x))^2=4g^2(x)f(x) (mod x^2n)
	//		
	//		 	 	g^2(x)+f(x)
	//	   		(---------------)^2        = f(x) (mod x^2n)
	//		   		  2g(x)
	//		
	//		(g(x)/2+f(x)*g-1(x)/2)^2 = f(x) (mod x^2n)
	//		
	//			new g(x)= g(x)/2+f(x)*g-1(x)/2
	//		
	void Sqrt(TYPE *a,TYPE *b,int N) {
 
		static TYPE c[MAXN],t[MAXN];
		if(N==1) {
			b[0]=sqrt(a[0]);
			return ;
		}
		Sqrt(a,b,N>>1);
		const TYPE inv2=pow(2,mod-2);
 
		const int mh=N<<1;
		memcpy(t,a,sizeof(TYPE)*N);
		memset(c,0,sizeof(TYPE)*N);
		inv(b,c,N);
		NTT(t,mh,1);NTT(b,mh,1);NTT(c,mh,1);
		for(int i=0;i<mh;++i) {
			b[i]=(1ll*inv2*b[i]%mod+1ll*t[i]*c[i]%mod*inv2%mod)%mod;
		}NTT(b,mh,-1);
		memset(b+N,0,sizeof(TYPE)*N);//printf("%d 2333:\n",N);
	}
	
 
 
	//calc a(x)+=1
	TYPE*self_add(TYPE *a,TYPE i) {(++a[i])%=mod;return a;}
 
 
 
	//calc f'a(x) dx
	TYPE* sigma(TYPE *a,TYPE *b,int N) {
		for(int i=1;i<=N;++i) {
			b[i]=1ll*a[i-1]*pow(i,mod-2)%mod;
		}b[0]=0;
		//print(b,N);
		return b;
	}
 
 
 
	//calc a'(x)
	TYPE* omiga(TYPE*a,TYPE*b,int N) {
		for(int i=1;i<N;++i) {
			b[i-1]=1ll*a[i]*i%mod;
		}b[N-1]=0;
		return b;
	}
 
 
 
	//calc ln a(x)
	//
	//
	//		b(x)    = ln a(x)
	//					a'(x)
	//		b'(x)	= ----------
	//					a(x)
	//					
	//		b(x)    = f b'(x)
	//		
	TYPE ln(TYPE *a,TYPE *b,int N) {
		static TYPE oa[MAXN],ia[MAXN];
		const int mh=N<<1;
		memset(oa,0,sizeof(TYPE)*mh);
		memset(ia,0,sizeof(TYPE)*mh);
		omiga(a,oa,N);inv(a,ia,N);
		NTT(oa,mh,1);NTT(ia,mh,1);
		for(int i=0;i<mh;++i) {
			oa[i]=1ll*oa[i]*ia[i]%mod;
		}NTT(oa,mh,-1);
		//printf("233333333333333333\n");
		sigma(oa,b,N);
		memset(b+N,0,sizeof(TYPE)*N);
	}
 
 
 
	//calc exp a(x)
	//
	//	Newtown : x'=x-f(x)/f'(x)
	//	
	void exp(TYPE *a,TYPE *b,int N) {
		static TYPE c[MAXN];
		if(N==1) {b[0]=1;return ;}
		exp(a,b,N>>1);
		const int mh=N<<1;
		memset(c,0,sizeof(TYPE)*mh);
		ln(b,c,N);
		for(int i=0;i<N;++i) {
			c[i]=((i==0)+a[i]-c[i]+mod)%mod;
		}NTT(c,mh,1);NTT(b,mh,1);
		for(int i=0;i<mh;++i){
			b[i]=1ll*b[i]*c[i]%mod;
		}NTT(b,mh,-1);
		memset(b+N,0,sizeof(TYPE)*N);
	}
 
 
 
	// clac a^k(x)
	// a^k(x)=exp(k*ln(a(x)))
	// 
	void pow(TYPE*a,int k,int N) {
		static TYPE c[MAXN]={0};
		ln(a,c,N);
		for(int i=0;i<N;++i)
			c[i]=1ll*c[i]*k%mod;
		memset(a,0,sizeof(TYPE)*N<<1);
		exp(c,a,N);//print(a,N);
	}
}
TYPE a[MAXN],b[MAXN];
int main() {
	freopen("polynomial.in","r",stdin);
	freopen("polynomial.out","w",stdout);
	using namespace Number_Theory;
	int M,K,N;
	scanf("%d%d",&M,&K);
	for(N=1;N<=M;N<<=1);
	for(int i=0;i<M;a[i++]=input());
	//NTT(a,N,1);NTT(a,N,-1);print(a,N);
	Sqrt(a,b,N);	memset(a,0,sizeof(TYPE)*N<<1);//print(b,N);
	inv(b,a,N);		memset(b,0,sizeof(TYPE)*N<<1);
	sigma(a,b,N);	memset(a,0,sizeof(TYPE)*N<<1);
	exp(b,a,N);		memset(b,0,sizeof(TYPE)*N<<1);
	inv(a,b,N);		memset(a,0,sizeof(TYPE)*N<<1);
	self_add(b,0);
	ln(b,a,N);		memset(b,0,sizeof(TYPE)*N<<1);
	self_add(a,0);	
	pow(a,K,N);		//print(a,N);
	omiga(a,b,N); b[M-1]=0;
	if(M==100000)printf("%d\n",SPFA);
	for(int i=0;i<M;print(b[i++]));
	//printf("\n%d",clock());
	return 8==3;
}