正题

题目链接:https://www.luogu.com.cn/problem/CF848E


题目大意

\(2n\)个花排成一个圆环,\(n\)种颜色每种两个,要求两个相同颜色之间最小距离为\(1,2\)或\(n\)。

对于一种染色方案的权值为:删除掉距离为\(n\)的颜色后,剩下的连续段长度的乘积。

求所有方案的染色之和对\(998244353\)取模。

\(1\leq n\leq 50000\)


解题思路

环好像很麻烦,先考虑线段上的,现在有两个长度为\(n\)的数列,然后距离为\(n\)的点之间对应。染色可以看为连接两个点。

然后设\(g_i\)表示不使用跨越数列的连线,涂\(i\)个的方案数,那么有\(g_i=g_{i-2}+g_{i-4}\)(相邻的连接/两个都是隔着对方连)。

然后考虑有跨越数列的线的方案,且没有其他连线跨过这条线,\(f0_i\)表示第\(i\)个是满足条件的线的权值和。\(f1_i\)则表示刚好有一对距离为\(2\)的点对跨越这个线的权值和。

那么有转移方程

\[f0_i=g_ii^2+\sum_{j=0}^{i-1}g_jj^2f0_{i-j-1}+\sum_{j=0}^{i-3}g_j(j+1)^2f1_{i-j-3}
\]

(第一个是全程没有其他横跨边,第二个是上一条横跨边两边没有同色,第三个是上一条横跨边两边有同色)

同理可以得到\(f1\)的方程

\[f1_i=g_i(i+1)^2+\sum_{j=0}^{i-1}g_j(j+1)^2f0_{i-j-1}+\sum_{j=0}^{i-3}g_j(j+2)^2f1_{i-j-3}
\]

得到\(f0\)和\(f1\)之后,看一下\(f0,f1\)都是最左边没有距离为\(2\)的边越过的,但是我们转换到环上的时候需要考虑这种情况,所以我们设\(f2_i\)表示左右两边的横跨边都有同色的,中间距离为\(i\)的权值和。

方程是

\[f2_i=g_i(i+2)^2+\sum_{j=0}^{i-1}g_j(j+1)^2f0_{i-j-1}+\sum_{j=0}^{j-3}g_j(j+2)^2f1_{i-j-3}
\]

然后考虑转换到行上。

如果只有一个点对距离是\(n\),那么贡献是\((n-1)\),有\(n\)种旋转方法,如果这个点对两边没有同色点,那么方案数是\(g_{n-1}\),否则是\(g_{n-3}\),所以这种情况的方案是\((n-1)^2n(g_{n-1}+g_{n-3})\)

然后剩下的我们可以先固定\(1\sim n+1\),然后枚举第二个距离为\(n\)的点对。设为\(i\),那贡献就是$$i(i-1)^2(g_{i-1}f0_{n-i-1}+2g_{i-2}f1_{n-i-2}+g_{i-3}f2_{n-i-3})$$

然后前面求\(f0,f1,f2\)都可以用分治\(NTT\)搞。

时间复杂度\(O(n\log^2 n)\)

如果用生成函数再推推可以分别得到\(O(n)\)和\(O(n\log n)\)的方法。

还有可以用生成函数发现这是一个\(16\)项的线性递推式,打出前面的表再用高斯消元得到系数,可以把时间优化到\(log\)级别

路还很长啊


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,P=998244353;
ll n,m,r[N],g[N],h[3][N],f[3][N];
ll t[3][N],T[2][N],z[4][N];
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
void Glen(ll n){
m=1;while(m<=n)m<<=1;
for(ll i=0;i<m;i++)
r[i]=(r[i>>1]>>1)|((i&1)?(m>>1):0);
return;
}
void NTT(ll *f,ll op){
for(ll i=0;i<m;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(ll p=2;p<=m;p<<=1){
ll len=(p>>1),tmp=power(3,(P-1)/p);
if(op==-1)tmp=power(tmp,P-2);
for(ll k=0;k<m;k+=p){
ll buf=1;
for(ll i=k;i<k+len;i++){
ll tt=buf*f[i+len]%P;
f[i+len]=(f[i]-tt+P)%P;
f[i]=(f[i]+tt)%P;
buf=buf*tmp%P;
}
}
}
if(op==-1){
ll inv=power(m,P-2);
for(ll i=0;i<m;i++)
f[i]=f[i]*inv%P;
}
return;
}
void CDQ(ll l,ll r){
if(l==r){
(f[0][l]+=h[0][l])%=P;
(f[1][l]+=h[1][l])%=P;
return;
}
ll mid=(l+r)>>1;CDQ(l,mid);
Glen((r-l+1)*2);
for(ll i=0;i<m;i++)
t[0][i]=t[1][i]=t[2][i]=T[0][i]=T[1][i]=0;
for(ll i=0;i<=r-l+1;i++)
t[0][i]=h[0][i],t[1][i]=h[1][i],t[2][i]=h[2][i];
for(ll i=0;i<=mid-l;i++)
T[0][i]=f[0][i+l],T[1][i]=f[1][i+l];
NTT(t[0],1);NTT(t[1],1);NTT(t[2],1);
NTT(T[0],1);NTT(T[1],1);
for(ll i=0;i<m;i++){
z[0][i]=t[0][i]*T[0][i]%P,z[1][i]=t[1][i]*T[1][i]%P;
z[2][i]=t[1][i]*T[0][i]%P,z[3][i]=t[2][i]*T[1][i]%P;
}
NTT(z[0],-1);NTT(z[1],-1);NTT(z[2],-1);NTT(z[3],-1);
for(ll i=0;i<=r-l+1;i++){
if(l+i+1>mid&&l+i+1<=r){
f[0][l+i+1]=(f[0][l+i+1]+z[0][i])%P;
f[1][l+i+1]=(f[1][l+i+1]+z[2][i])%P;
}
if(l+i+3>mid&&l+i+3<=r){
f[0][l+i+3]=(f[0][l+i+3]+z[1][i])%P;
f[1][l+i+3]=(f[1][l+i+3]+z[3][i])%P;
}
}
CDQ(mid+1,r);return;
}
void solve(ll l,ll r){
if(l==r){(f[2][l]+=h[2][l])%=P;return;}
ll mid=(l+r)>>1;solve(l,mid);
Glen((r-l+1)*2);
for(ll i=0;i<m;i++)
t[1][i]=t[2][i]=T[0][i]=T[1][i]=0;
for(ll i=0;i<=r-l+1;i++)
t[1][i]=h[1][i],t[2][i]=h[2][i];
for(ll i=0;i<=mid-l;i++)
T[0][i]=f[1][l+i],T[1][i]=f[2][l+i];
NTT(t[1],1);NTT(t[2],1);NTT(T[0],1);NTT(T[1],1);
for(ll i=0;i<m;i++){
z[0][i]=t[1][i]*T[0][i]%P;
z[1][i]=t[2][i]*T[1][i]%P;
}
NTT(z[0],-1);NTT(z[1],-1);
for(ll i=0;i<r-l+1;i++){
if(l+i+1>mid&&l+i+1<=r)
(f[2][l+i+1]+=z[0][i])%=P;
if(l+i+3>mid&&l+i+3<=r)
(f[2][l+i+3]+=z[1][i])%=P;
}
solve(mid+1,r);
return;
}
signed main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%lld",&n);g[0]=g[2]=1;
for(ll i=4;i<=n;i++)
g[i]=(g[i-4]+g[i-2])%P;
for(ll i=0;i<=n;i++){
h[0][i]=g[i]*i%P*i%P;
h[1][i]=g[i]*(i+1)%P*(i+1)%P;
h[2][i]=g[i]*(i+2)%P*(i+2)%P;
}
CDQ(0,n);
solve(0,n);
ll ans=(g[n-1]+g[n-3])*(n-1)%P*(n-1)%P*n%P;
for(ll i=2;i<n-1;i++){
ll tmp=g[i-1]*f[0][n-i-1]%P;
tmp=(tmp+2*g[i-2]*f[1][n-i-2]%P)%P;
tmp=(tmp+g[i-3]*f[2][n-i-3]%P)%P;
tmp=tmp*i%P*(i-1)%P*(i-1)%P;
ans=(ans+tmp)%P;
}
printf("%lld\n",ans);
return 0;
}

最新文章

  1. Django基础,Day8 - 管理后台定制显示
  2. solr5.2 mysql 增量索引
  3. Oracle 表分区
  4. easyUI框架之学习3--表格datagrid
  5. python set add 导致问题 TypeError: unhashable type: &#39;list&#39;
  6. 1.1 ASP.NET MVC简介
  7. What are Upgrade, Product and Package Codes used for? By pusu
  8. org.springframework.web.servlet.view.InternalResourceViewResolver
  9. Android Studio编译好的apk放在哪里?
  10. ArcGIS制图——多图层道路压盖处理
  11. Lua 环境结构 --Linux
  12. SpringMVC中Controller
  13. CodeForces 645D Robot Rapping Results Report
  14. Python实战之实现简单的购物车系统
  15. php+中文分词scws+sphinx+mysql打造千万级数据全文搜索
  16. nginx简单安装设置
  17. 构建现代Web应用时究竟是选择传统web应用还是SPA
  18. JavaScript学习之自动轮播图片
  19. zip4j压缩
  20. repo跟svn的区别

热门文章

  1. &quot;image watch&quot; for QtCreator
  2. Asp.NetCore 中Aop的应用
  3. 【ArcGIS】 设置管段的流向
  4. android Handler消息通信
  5. 【SpringMVC】域对象共享数据
  6. 有关Java动态数组的一个小问题
  7. 国内Git官网下载windows版本慢的问题,推荐一个国内镜像
  8. Git使用教程六
  9. 基于源码编译的lnmp架构实现论坛的搭建及memcache的应用
  10. vue 接入 vod-js-sdk-v6.js 完成视频上传