zoukankan      html  css  js  c++  java
  • 【Codeforces 848 E】Days of Floral Colours(生成函数+DP)

    传送门

    考虑把环拆成两行
    相对方向的同色看做两行相同位置同色
    实际上只有四种可能的拼法
    AAABABACACAA;ABAB;ACA;C;CC是和对面的同色的)
    首先设gig_i表示只由前两种情况拼起来的长度为ii的段的方案数
    那么有gi=gi2+gi4g_i=g_{i-2}+g_{i-4}
    g0i=gii2,g1i=gi(i+1)2,g2i=gi(i+2)2g_{0i}=g_ii^2,g_{1i}=g_i(i+1)^2,g_{2i}=g_i(i+2)^2
    f0if_{0i}表示为CCC……C中间……长度为ii的方案数
    f1if_{1i}表示为CACAC……ACA中间长度为ii的方案数
    f2if_{2i}表示ACAACAACA……ACA中间长度为ii的方案数
    那么枚举两段拼接可以得到

    f0n=g0n+i+j=n1f0ig0j+i+j=n3g1if1jf_{0n}=g_{0n}+sum_{i+j=n-1}f_{0i}g_{0j}+sum_{i+j=n-3}g_{1i}f_{1j}
    f1n=g1n+i+j=n1f0ig1j+i+j=n3g2if1jf_{1n}=g_{1n}+sum_{i+j=n-1}f_{0i}g_{1j}+sum_{i+j=n-3}g_{2i}f_{1j}
    f2n=g2n+i+j=n1f1ig1j+i+j=n3g2if2jf_{2n}=g_{2n}+sum_{i+j=n-1}f_{1i}g_{1j}+sum_{i+j=n-3}g_{2i}f_{2j}

    其实这里可以分治NTTNTT做了

    考虑写成生成函数的形式

    f0(x)=g0(x)+f0(x)g0(x)x+g1(x)f1(x)x3f_0(x)=g_0(x)+f_0(x)g_0(x)x+g_1(x)f_1(x)x^3
    f1(x)=g1(x)+f0(x)g1(x)x+g2(x)f1(x)x3f_1(x)=g_1(x)+f_0(x)g_1(x)x+g_2(x)f_1(x)x^3
    f2(x)=g2(x)+f1(x)g1(x)x+g2(x)f2(x)x3f_2(x)=g_2(x)+f_1(x)g_1(x)x+g_2(x)f_2(x)x^3

    可以解方程解出f0,f1,f2f0,f1,f2
    若设b=g0g2x4g2x3g0x+1g12x4=(g0x1)(g2x31)g1x4b=g_0g_2x^4-g_2x^3-g_0x+1-g_1^2x^4=(g_0x-1)(g_2x^3-1)-g_1x^4

    那么f0=g1x3g0(g2x31)bf_0=frac{g_1x^3-g_0(g_2x^3-1)}{b}
    f1=g1bf_1=frac{g_1}{b}
    f2=g2+g1f1x1g2x3f_2=frac{g_2+g_1f_1x}{1-g_2x^3}

    于是用多项式求逆即可求出f0,f1,f2f_0,f_1,f_2
    考虑统计答案

    首先只由一对相对的颜色时,贡献为n(n1)2(gn1+gn3)n*(n-1)^2(g_{n-1}+g_{n-3})
    否则考虑对于一种方案,看做钦定11号点以及n+1n+1同色后旋转一定角度得到的
    然后考虑第二个相对同色的离11号点的距离
    那么中间这些都是可以旋转的角度

    可以得到贡献为i=2n2i(i1)2(gi1f0 ni2+2gi2f1 ni2+gi3f2 ni3)sum_{i=2}^{n-2}i*(i-1)^2(g_{i-1}f_{0 n-i-2}+2g_{i-2}f_{1 n-i-2}+g_{i-3}f_{2 n-i-3})

    加起来即可

    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define re register
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define ll long long
    #define se second
    #define bg begin
    cs int RLEN=(1<<20)+1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=res*10+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp&a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp&a,tp b){a>b?a=b:0;}
    cs int mod=998244353,G=3;
    inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
    inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
    inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
    inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
    inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
    inline void Mul(int &a,int b){static ll r;r=1ll*a*b,a=(r>=mod)?(r%mod):r;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    inline int fix(int x){return (x<0)?(x+mod):x;}
    typedef vector<int> poly;
    cs int C=18;
    int *w[C+1];
    int rev[(1<<C)|1];
    inline void init_rev(int lim){
    	for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
    }
    inline void init_w(){
    	for(int i=1;i<=C;i++)w[i]=new int[1<<(i-1)];
    	int wn=ksm(G,(mod-1)/(1<<C));
    	w[C][0]=1;
    	for(int i=1,l=1<<(C-1);i<l;i++)w[C][i]=mul(w[C][i-1],wn);
    	for(int i=C-1;i;i--)
    	for(int j=0,l=1<<(i-1);j<l;j++)w[i][j]=w[i+1][j<<1];
    }
    inline void ntt(poly &f,int lim,int kd){
    	for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
    	for(int l=1,a0,a1,mid=1;mid<lim;mid<<=1,l++)
    	for(int i=0;i<lim;i+=mid<<1)
    	for(int j=0;j<mid;j++)
    	a0=f[i+j],a1=mul(f[i+j+mid],w[l][j]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
    	if(kd==-1){
    		reverse(f.bg()+1,f.bg()+lim);
    		for(int i=0,iv=Inv(lim);i<lim;i++)Mul(f[i],iv);
    	}
    }
    inline poly operator +(poly a,poly b){
    	a.resize(max(a.size(),b.size()));
    	for(int i=0;i<b.size();i++)Add(a[i],b[i]);
    	return a;
    }
    inline poly operator -(poly a,poly b){
    	a.resize(max(a.size(),b.size()));
    	for(int i=0;i<b.size();i++)Dec(a[i],b[i]);
    	return a;
    }
    inline poly operator *(poly a,poly b){
    	int deg=a.size()+b.size()-1,lim=1;
    	if(deg<=32){
    		poly c(deg,0);
    		for(int i=0;i<a.size();i++)
    		for(int j=0;j<b.size();j++)
    		Add(c[i+j],mul(a[i],b[j]));
    		return c;
    	}
    	while(lim<deg)lim<<=1;
    	init_rev(lim);
    	a.resize(lim),b.resize(lim);
    	ntt(a,lim,1),ntt(b,lim,1);
    	for(int i=0;i<lim;i++)Mul(a[i],b[i]);
    	ntt(a,lim,-1),a.resize(deg);
    	return a;
    }
    inline poly Inv(poly a,int deg){
    	poly b(1,Inv(a[0])),c;
    	for(int lim=4;lim<(deg<<2);lim<<=1){
    		init_rev(lim);c.resize(lim>>1);
    		for(int i=0;i<(lim>>1);i++)
    		c[i]=(i<a.size())?a[i]:0;
    		b.resize(lim),c.resize(lim);
    		ntt(b,lim,1),ntt(c,lim,1);
    		for(int i=0;i<lim;i++)b[i]=mul(b[i],dec(2,mul(b[i],c[i])));
    		ntt(b,lim,-1),b.resize(lim>>1);
    	}b.resize(deg);return b;
    }
    cs int N=50004;
    poly g1,g2,g0,f1,f2,f0,x1,x2,x3;
    int g[N],n;
    inline int P(int x){return mul(x,x);}
    int main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#endif
    	n=read();init_w();
    	g[0]=g[2]=1,x1.resize(2),x2.resize(3),x3.resize(4);
    	x1[1]=1,x2[2]=1,x3[3]=1;
    	g1.resize(n+1),g2.resize(n+1),g0.resize(n+1);
    	for(int i=4;i<=n;i+=2)g[i]=add(g[i-2],g[i-4]);
    	for(int i=0;i<=n;i+=2)g0[i]=mul(g[i],P(i)),g1[i]=mul(g[i],P(i+1)),g2[i]=mul(g[i],P(i+2));
    	poly b=g2,c=g0,d,e;
    	c.pb(0);
    	for(int i=c.size()-1;i;i--)c[i]=c[i-1];
    	c[0]=mod-1;//c=g0x-1
    	b.resize(n+4);
    	for(int i=b.size()-1;i>=3;i--)b[i]=b[i-3];
    	b[2]=b[1]=0,b[0]=mod-1;//d=g2x^3-1
    	d=b,b=b*c,c=g1,c.resize(n+3);
    	for(int i=c.size()-1;i>1;i--)c[i]=c[i-2];
    	c[1]=0,c[0]=0,c=c*c;
    	b=b-c;//c=g1^2x^4
    	for(int i=0;i<c.size()-2;i++)c[i]=c[i+1];
    	c.pop_back();
    	b=Inv(b,n+1);
    	f1=g1*b;
    	f0=(c-g0*d)*b;
    	for(int i=0;i<d.size();i++)d[i]=dec(0,d[i]);
    	d=Inv(d,n+1);
    	f2=g1*f1;
    	f2.pb(0);
    	for(int i=f2.size()-1;i;i--)f2[i]=f2[i-1];
    	f2[0]=0;
    	f2=(f2+g2)*d;
    //	for(int i=0;i<=n;i++)cout<<f0[i]<<" "<<f1[i]<<" "<<f2[i]<<'
    ';
    	int ret=mul(mul(add(g[n-1],g[n-3]),P(n-1)),n);
    	for(int i=2;i<=n-2;i++){
    		int now=mul(g[i-1],f0[n-i-1]);
    		Add(now,mul(2,mul(g[i-2],f1[n-i-2])));
    		if(i>2&&n-i>=3)Add(now,mul(g[i-3],f2[n-i-3]));
    		Add(ret,mul(mul(i,P(i-1)),now));
    	}
    	cout<<ret;
    }
    
  • 相关阅读:
    软件工程(2019)第一次作业
    软件工程-第二次结对编程
    软件工程-第一次结对编程
    java-最大连续子数组和(最大字段和)
    软件工程-第二次作业
    软件工程-第一次作业
    windows下安装oracle11g测试是否成功与监听器问题和网页控制台登录
    java jdk13的安装与环境变量的配置(jre手动生成)
    结对编程第二次作业
    结对作业
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328332.html
Copyright © 2011-2022 走看看