• 联考20200617 T3 「雅礼集训 2018 Day8」C


    题目传送门

    分析:
    跑去写了一下烷基计数(博客),这道题要先会求烷基的生成函数
    我们假设求出来了烷基的生成函数为(A)


    (蒟蒻表示被开除人籍了,看不大懂)
    反正先照着式子写一下吧
    (省选不退役再回来补吧2333)

    upd:
    退役失败,回来补坑
    以下为口胡。。。
    P函数是确定一个重心,四面接烷基的方案,使用Ploya定理去重
    Q函数是去除沿某一条边为对称轴翻转同构,把那条边断开挤一个点在里面
    S函数是P-Q里面多减去的两个重心的方案,需要加回来
    (不太明白,这种神仙题考场上也写不出来的2333)

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    
    #define maxn 2000005
    #define MOD 998244353
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int N=100000;
    int F[maxn],F2[maxn],F3[maxn],F4[maxn],rev[maxn];
    int ans[maxn];
    int Wl,Wl2,w[maxn];
    
    inline int ksm(int num,int k)
    {
    	int ret=1;
    	for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
    	return ret;
    }
    void init(int len)
    {
    	Wl=w[0]=1;
    	while((Wl<<1)<=len)Wl<<=1;
    	w[1]=ksm(3,(MOD-1)/(Wl<<1)),Wl2=Wl<<1;
    	for(int i=2;i<=Wl2;i++)w[i]=1ll*w[i-1]*w[1]%MOD;
    }
    inline int upd(int x){return x<MOD?x:x-MOD;}
    
    inline void getrev(int len)
    {for(int i=0;i<len;i++)rev[i]=(rev[i>>1]>>1)|(i&1?len>>1:0);}
    inline void NTT(int *A,int len,int opt)
    {
    	for(int i=0;i<len;i++)if(i<rev[i])swap(A[i],A[rev[i]]);
    	for(int i=1,B=Wl;i<len;i<<=1,B>>=1)
    	{
    		for(int j=0,t=i<<1;j<len;j+=t)for(int k=0,x=0;k<i;k++,x+=B)
    		{
    			int v=1ll*A[i+j+k]*w[opt==1?x:Wl2-x]%MOD;
    			A[i+j+k]=upd(A[j+k]-v+MOD),A[j+k]=upd(A[j+k]+v);
    		}
    	}
    	if(!~opt)for(int i=0,Inv=ksm(len,MOD-2);i<len;i++)A[i]=1ll*A[i]*Inv%MOD;
    }
    
    inline void getinv(int *A,int *B,int n)
    {
    	static int T[maxn];
    	for(int i=0;i<(n<<1);i++)B[i]=0;
    	B[0]=ksm(A[0],MOD-2);
    	for(int len=2;len<=n;len<<=1)
    	{
    		for(int i=0;i<len;i++)T[i]=A[i],T[i+len]=0;
    		getrev(len<<1);
    		NTT(T,len<<1,1),NTT(B,len<<1,1);
    		for(int i=0;i<(len<<1);i++)B[i]=1ll*B[i]*upd(2-1ll*T[i]*B[i]%MOD+MOD)%MOD;
    		NTT(B,len<<1,-1);
    		for(int i=len;i<(len<<1);i++)B[i]=0;
    	}
    }
    inline void solve(int n)
    {
    	static int G[maxn],H[maxn],S[maxn],C[maxn],T[maxn];
    	F[0]=1;
    	for(int i=2;i<=n;i<<=1)
    	{
    		for(int j=0;j<i;j++)T[j]=F[j],S[j]=C[j]=T[j+i]=S[j+i]=C[j+i]=0;
    		for(int j=0;j<i;j+=2)S[j]=F[j/2];
    		for(int j=0;j<i;j+=3)C[j]=F[j/3];
    		getrev(i<<1);
    		NTT(T,i<<1,1),NTT(S,i<<1,1);
    		for(int j=0;j<(i<<1);j++)G[j]=1ll*T[j]*(1ll*T[j]*T[j]%MOD+3ll*S[j])%MOD,H[j]=3*(1ll*T[j]*T[j]+S[j])%MOD;
    		NTT(G,i<<1,-1),NTT(H,i<<1,-1);
    		for(int j=i;j<(i<<1);j++)G[j]=H[j]=0;
    		for(int j=i-1;j;j--)G[j]=((1ll*G[j-1]+2ll*C[j-1]-6ll*F[j])%MOD+MOD)%MOD,H[j]=H[j-1];
    		G[0]=0,H[0]=MOD-6;
    		NTT(G,i<<1,1),getinv(H,T,i),NTT(T,i<<1,1);
    		for(int j=0;j<(i<<1);j++)G[j]=1ll*G[j]*T[j]%MOD;
    		NTT(G,i<<1,-1);
    		for(int j=0;j<i;j++)F[j]=(F[j]-G[j]+MOD)%MOD;
    	}
    }
    
    inline void work(int len)
    {
    	static int A1[maxn],A2[maxn],A3[maxn],A4[maxn],T[maxn];
    	for(int i=0;i*4<len;i++)ans[i*4+1]=1ll*ksm(4,MOD-2)*F[i]%MOD;
    	for(int i=0;i*2<len;i++)ans[i*2]=F[i];
    	getrev(len);
    	NTT(F,len,1),NTT(F2,len,1),NTT(F3,len,1),NTT(F4,len,1);
    	for(int i=0;i<len;i++)
    	{
    		A1[i]=1ll*F[i]*F[i]%MOD*F[i]%MOD*F[i]%MOD;
    		A2[i]=3ll*F2[i]*F2[i]%MOD;
    		A3[i]=6ll*F[i]*F[i]%MOD*F2[i]%MOD;
    		A4[i]=8ll*F[i]*F3[i]%MOD;
    		T[i]=(1ll*A1[i]+A2[i]+A3[i]+A4[i])*ksm(24,MOD-2)%MOD;
    	}
    	NTT(T,len,-1);
    	for(int i=0;i<len;i++)ans[i+1]=(ans[i+1]+T[i])%MOD;
    	for(int i=0;i<len;i++)T[i]=(1ll*F[i]*F[i]%MOD*ksm(2,MOD-2)+1ll*F2[i]*ksm(2,MOD-2)-F[i])%MOD;
    	NTT(T,len,-1);
    	for(int i=0;i<len;i++)ans[i]=upd(ans[i]-T[i]+MOD);
    }
    
    int main()
    {
    	int len=1;
    	while(len<=4*N)len<<=1;
    	init(len);
    	solve(len>>2);
    	for(int i=0;i<len;i++)F2[i]=i%2?0:F[i/2];
    	for(int i=0;i<len;i++)F3[i]=i%3?0:F[i/3];
    	for(int i=0;i<len;i++)F4[i]=i%4?0:F[i/4];
    	work(len);
    	int T=getint();
    	while(T--)
    	{
    		int n=getint();
    		printf("%d
    ",ans[n]);
    	}
    }
    

  • 相关阅读:
    Vue.Draggable实现拖拽效果(快速使用)
    1.从面向过程到面向对象的过渡
    微信支付流程
    2.js原型的基本概念
    POST和GET请求的区别
    vue-router2.0
    vue列表渲染,以及鼠标点击改变样式的问题
    复杂数组结构的深拷贝
    高德地图将字符串地址转为经纬度的一个demo
    数组对象排序
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13157722.html
Copyright © 2020-2023  润新知