当前位置: 代码迷 >> 综合 >> 【Codeforces 848 E】Days of Floral Colours(生成函数+DP)
  详细解决方案

【Codeforces 848 E】Days of Floral Colours(生成函数+DP)

热度:12   发布时间:2024-01-26 04:25:21.0

传送门

考虑把环拆成两行
相对方向的同色看做两行相同位置同色
实际上只有四种可能的拼法
A A A B A B A C A C AA;ABAB;ACA;C; C C 是和对面的同色的)
首先设 g i g_i 表示只由前两种情况拼起来的长度为 i i 的段的方案数
那么有 g i = g i ? 2 + g i ? 4 g_i=g_{i-2}+g_{i-4}
g 0 i = g i i 2 , g 1 i = g i ( i + 1 ) 2 , g 2 i = g i ( i + 2 ) 2 g_{0i}=g_ii^2,g_{1i}=g_i(i+1)^2,g_{2i}=g_i(i+2)^2
f 0 i f_{0i} 表示为 C C C……C 中间 …… 长度为 i i 的方案数
f 1 i f_{1i} 表示为 C A C A C……ACA 中间长度为 i i 的方案数
f 2 i f_{2i} 表示 A C A A C A ACA……ACA 中间长度为 i i 的方案数
那么枚举两段拼接可以得到

f 0 n = g 0 n + i + j = n ? 1 f 0 i g 0 j + i + j = n ? 3 g 1 i f 1 j f_{0n}=g_{0n}+\sum_{i+j=n-1}f_{0i}g_{0j}+\sum_{i+j=n-3}g_{1i}f_{1j}
f 1 n = g 1 n + i + j = n ? 1 f 0 i g 1 j + i + j = n ? 3 g 2 i f 1 j f_{1n}=g_{1n}+\sum_{i+j=n-1}f_{0i}g_{1j}+\sum_{i+j=n-3}g_{2i}f_{1j}
f 2 n = g 2 n + i + j = n ? 1 f 1 i g 1 j + i + j = n ? 3 g 2 i f 2 j f_{2n}=g_{2n}+\sum_{i+j=n-1}f_{1i}g_{1j}+\sum_{i+j=n-3}g_{2i}f_{2j}

其实这里可以分治 N T T NTT 做了

考虑写成生成函数的形式

f 0 ( x ) = g 0 ( x ) + f 0 ( x ) g 0 ( x ) x + g 1 ( x ) f 1 ( x ) x 3 f_0(x)=g_0(x)+f_0(x)g_0(x)x+g_1(x)f_1(x)x^3
f 1 ( x ) = g 1 ( x ) + f 0 ( x ) g 1 ( x ) x + g 2 ( x ) f 1 ( x ) x 3 f_1(x)=g_1(x)+f_0(x)g_1(x)x+g_2(x)f_1(x)x^3
f 2 ( x ) = g 2 ( x ) + f 1 ( x ) g 1 ( x ) x + g 2 ( x ) f 2 ( x ) x 3 f_2(x)=g_2(x)+f_1(x)g_1(x)x+g_2(x)f_2(x)x^3

可以解方程解出 f 0 , f 1 , f 2 f0,f1,f2
若设 b = g 0 g 2 x 4 ? g 2 x 3 ? g 0 x + 1 ? g 1 2 x 4 = ( g 0 x ? 1 ) ( g 2 x 3 ? 1 ) ? g 1 x 4 b=g_0g_2x^4-g_2x^3-g_0x+1-g_1^2x^4=(g_0x-1)(g_2x^3-1)-g_1x^4

那么 f 0 = g 1 x 3 ? g 0 ( g 2 x 3 ? 1 ) b f_0=\frac{g_1x^3-g_0(g_2x^3-1)}{b}
f 1 = g 1 b f_1=\frac{g_1}{b}
f 2 = g 2 + g 1 f 1 x 1 ? g 2 x 3 f_2=\frac{g_2+g_1f_1x}{1-g_2x^3}

于是用多项式求逆即可求出 f 0 , f 1 , f 2 f_0,f_1,f_2
考虑统计答案

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

可以得到贡献为 i = 2 n ? 2 i ? ( i ? 1 ) 2 ( g i ? 1 f 0   n ? i ? 2 + 2 g i ? 2 f 1   n ? i ? 2 + g i ? 3 f 2   n ? i ? 3 ) \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 Stargazerfreopen("lx.cpp","r",stdin);#endifn=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-1b.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-1d=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^4for(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]<<'\n';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;
}
  相关解决方案