记录编号 363786 评测结果 AAAAAAAAAA
题目名称 [HEOI 2016] 求和 最终得分 100
用户昵称 GravatarYGOI_真神名曰驴蛋蛋 是否通过 通过
代码语言 C++ 运行时间 1.298 s
提交时间 2017-01-13 10:50:55 内存使用 8.03 MiB
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef unsigned int UINT;
const int MAXN=1E6+10;
const UINT mod=998244353;
const UINT god=3;
inline UINT pow(UINT a,UINT b) {
	UINT ans=1;
	for(ans=1;b;b>>=1,a=1ull*a*a%mod) {
		if(b&1)ans=1ull*ans*a%mod;
	}return ans;
}
void rotate(UINT*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]);
	}
}
void NTT(UINT*a,int N,const int&is) {
	rotate(a,N);
	for(int m=2;m<=N;m<<=1) {
		const int mh=m>>1;
		const UINT wn=pow(god,is==1?(mod-1)-(mod-1)/m:(mod-1)/m);
		for(int r=0;r<N;r+=m) {
			UINT w=1;
			UINT*b=a+r;
			UINT*c=a+r+mh;
			for(int k=0;k<mh;++k) {
				const UINT u=b[k];
				const UINT v=1ull*c[k]*w%mod;
				b[k]=(0ll+u+v)%mod;
				c[k]=(0ll+mod+u-v)%mod;
				w=1ull*w*wn%mod;
			}
		}
	}
	if(is<0) {
		const UINT inv=pow(N,mod-2);
		for(int i=0;i<N;++i) {
			a[i]=1ull*a[i]*inv%mod;
		}
	}
}
UINT nn[MAXN];
UINT invn[MAXN];
UINT JS[MAXN];
UINT invJS[MAXN];
int Cpre(int N) {
	JS[0]=1;++N;
	for(int i=1;i<=N;++i) {
		JS[i]=1ull*JS[i-1]*i%mod;
	}invJS[N]=pow(JS[N],mod-2);
	for(int i=N-1;i>=0;--i){
		invJS[i]=1ull*invJS[i+1]*(i+1)%mod;
		invn[i+1]=1ull*invJS[i+1]*JS[i]%mod;
	}--N;invn[0]=0;
	for(int i=0;i<=N+1;++i) {
		nn[i]=pow(i,N+1);
	}return 0;
}
inline UINT Psum(UINT k,UINT N) {
	return k==0?1:(k==1? N+1 : 1ull*(mod+nn[k]-1)%mod*(invn[k-1])%mod )*invJS[k]%mod;
}
inline UINT Usum(UINT k) {
	return k&1?1ull*(mod-1)*invJS[k]%mod:invJS[k];
}
inline UINT Mul2(UINT j) {
	return 1ull*pow(2,j)*JS[j]%mod;
}
UINT a[MAXN],b[MAXN],c[MAXN];


int main() {
	freopen("heoi2016_sum.in","r",stdin);
	freopen("heoi2016_sum.out","w",stdout);
	UINT N,len;
	//printf("%u",mod);
	scanf("%u",&N);
	Cpre(N);
	//Test(N);
	for(int i=0;i<=N;++i) {
		a[i]=Usum(i);
		b[i]=Psum(i,N);
		//printf("[%d] %9u\n",i,a[i]);
	}
	for(len=1;len<=N+1;len<<=1);len<<=1;
	NTT(a,len,1);
	NTT(b,len,1);
	for(int i=0;i<len;++i) {
		c[i]=1ull*a[i]*b[i]%mod;
	}NTT(c,len,-1);
	UINT ans=0;
	for(int i=0;i<=N;++i) {
		//printf("[%d]%16u %16u\n",i,c[i],Mul2(i));
		ans=(ans+1ull*Mul2(i)*c[i]%mod)%mod;
	}printf("%u\n",ans);
	fclose(stdin);fclose(stdout);
	return 0;
}