记录编号 271211 评测结果 AAAAAAAAAA
题目名称 [HZOI 2015]疯狂的欧拉图 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 3.633 s
提交时间 2016-06-15 19:14:53 内存使用 12.29 MiB
显示代码纯文本
#define maxn 131072ul

#include <cmath>
#include <stdio.h>
#include <string.h>
#include <algorithm>

const int mod=1e9+7,M=32000;

int power(int p,long long k){
	int ret=1;
	while(k){
		if(k&1) ret=1ll*ret*p%mod;
		k>>=1ll,p=1ll*p*p%mod;
	} return ret;
}

namespace FFT{

	using namespace std;

	typedef long long ll;
	typedef long double ld;

	struct cpx{
		ld r,i;
		cpx(ld _r=0,ld _i=0){r=_r,i=_i;}
		cpx operator + (const cpx &x){return cpx(r+x.r,i+x.i);}
		cpx operator - (const cpx &x){return cpx(r-x.r,i-x.i);}
		cpx operator * (const cpx &x){return cpx(r*x.r-i*x.i,r*x.i+i*x.r);}
		cpx conj(){return cpx(r,-i);}
	}A[maxn],B[maxn];

	const ld pi=acos(-1.0);

	int N,a0[maxn],b0[maxn],a1[maxn],b1[maxn];

	void setlen(int len){
		N=1;
		for(;N<len;N<<=1);
		N<<=1; return;
	}

	void fft(cpx *f,int n,int flag){
		for(register int i=0,j=0;i<n;i++){
			if(i>j) std::swap(f[i],f[j]);
			for(int t=n>>1;(j^=t)<t;t>>=1);
		} register cpx wn,w,u,t;
		for(register int m=2,i,p,k;m<=n;m<<=1){
			w=cpx(1,0),wn=cpx(cos(2.0*pi/m),flag*sin(2.0*pi/m));
			for(i=0,p=m>>1;i<n;i+=m,w=cpx(1,0)) for(k=0;k<p;k++,w=w*wn)
				u=f[i+k],t=w*f[i+k+p],f[i+k]=u+t,f[i+k+p]=u-t;
		}
		if(flag==-1) for(register int i=0;i<n;i++) f[i].r/=n; return;
	}

	void mul(int *a,int *b,int *c){
		for(int i=0;i<N;i++) A[i]=cpx(a[i],b[i]);
		fft(A,N,1);
		for(int i=0,j;i<N;i++){
			j=(N-i)&(N-1);
			B[i]=(A[i]*A[i]-(A[j]*A[j]).conj())*cpx(0,-0.25);
		} fft(B,N,-1);
		for(int i=0;i<N;i++) c[i]=((long long)(B[i].r+0.5))%mod;
		return;
	}

	void mul_mod(int *a,int *b,int *c){
		for(int i=0;i<N;i++) c[i]=0;
		if(N<=128){
			for(int i=0;i<N;i++) for(int j=0;j<=i;j++){
				(c[i]+=1ll*a[j]*b[i-j]%mod)%=mod;
			} return;
		}
		for(int i=0;i<N;i++) a0[i]=a[i]/M,b0[i]=b[i]/M; mul(a0,b0,a0);
		for(int i=0;i<N;i++) c[i]=1ll*a0[i]*M*M%mod,a1[i]=a[i]%M,b1[i]=b[i]%M; mul(a1,b1,a1);
		for(int i=0;i<N;i++) c[i]=(a1[i]+c[i])%mod,a0[i]=(a0[i]+a1[i])%mod,a1[i]=a[i]/M+a[i]%M,b1[i]=b[i]/M+b[i]%M;	 mul(a1,b1,a1);
		for(int i=0;i<N;i++) c[i]=(1ll*M*(a1[i]-a0[i]+mod)%mod+c[i])%mod; return;
	}
};

int tmp[maxn],result[maxn],F[maxn],G[maxn],H[maxn],inv[maxn],invf[maxn];

void getInv(int *f,int *g,int n){
	static int tmp[maxn];
	if(n==1){ g[0]=power(f[0],mod-2); return; }
	getInv(f,g,n>>1); memcpy(tmp,f,sizeof(int)*n);
	memset(tmp+n,0,sizeof(int)*n); FFT::setlen(n);
	FFT::mul_mod(g,tmp,result);
	for(int i=0;i<n;i++) result[i]=(mod-result[i])%mod; (result[0]+=2)%=mod;
	memset(result+n,0,sizeof(int)*n);
	FFT::mul_mod(g,result,tmp);
	for(int i=0;i<n;i++) g[i]=tmp[i];
	memset(g+n,0,sizeof(int)*n); return;
}

int main(){
	freopen("Crazy_Graph.in","r",stdin);
    freopen("Crazy_Graph.out","w",stdout);
	int n; scanf("%d",&n);
	int N=1; for(;N<=n;N<<=1);
	inv[0]=inv[1]=invf[0]=1;
	for(register int i=2;i<N;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(register int i=1;i<N;i++) invf[i]=1ll*invf[i-1]*inv[i]%mod;
	for(register int i=1,gn;i<N;i++){
		gn=power(2,1ll*(i-1)*(i-2)/2ll);
		H[i]=1ll*gn*invf[i-1]%mod,G[i]=1ll*gn*invf[i]%mod;
	}
	G[0]=1,getInv(G,F,N); FFT::setlen(n),FFT::mul_mod(F,H,result);
	int rp=(1+1ll*n*(n-1)/2ll)%mod;
	printf("%d\n",1ll*result[n]*power(invf[n-1],mod-2)%mod*rp%mod);
	return 0;
}