官方题解:
http://codeforces.com/blog/entry/54233

就是由简入繁

1.序列处理,只考虑一个半圆

2.环形处理(其实这个就是多了旋转同构)

然后基于分割线邻居的跨越与否,分类讨论

g->没有分割线方案数(其实也可以变成贡献,但是太简单,之后乘上(i+0/1/2)也方便)

f0->有分割线,两边都没有选所有情况的贡献的和

f1->有分割线,两边选择了一个所有情况的贡献的和

f2->有分割线,两边都选择了所有情况的贡献的和

最后对于环

考虑除了中间割线,顺时针第一个割线的位置i,再对于跨越与否分4种情况讨论。可以逆时针旋转(i-2)个

对于式子,可以分治FFT

或者大力解二元方程,变成多项式求逆

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define int long long
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
template<class T>il void ot(T x){
x/?ot(x/):putchar(x%+'');
}
template<class T>il void prt(T a[],int st,int nd){
for(reg i=st;i<=nd;++i) printf("%lld ",a[i]);putchar('\n');
}
namespace Miracle{
const int N=*+;
const int mod=;
const int G=;
const int GI=;
int n;
ll f0[N],f1[N],f2[N];
ll g[N],g0[N],g1[N],g2[N];
ll x3g2[N],g12[N],ix3g2[N];
ll ni[N],t[N],p[N],l[N],q[N];
ll qm(ll x,ll y){
ll ret=;
while(y){
if(y&) ret=(ll)ret*x%mod;
x=(ll)x*x%mod;
y>>=;
}
return ret;
}
int rev[N];
void NTT(ll *f,int n,int typ){
// cout<<n<<endl;
for(reg i=;i<n;++i){
if(i<rev[i]) swap(f[i],f[rev[i]]);
}
for(reg p=;p<=n;p<<=){
ll gen;
if(typ==) gen=qm(G,(mod-)/p);
else gen=qm(GI,(mod-)/p);
for(reg l=;l<n;l+=p){
ll buf=;
for(reg k=l;k<l+p/;++k){
ll tmp=f[k+p/]*buf%mod;
f[k+p/]=(f[k]-tmp+mod)%mod;
f[k]=(f[k]+tmp)%mod;
buf=buf*gen%mod;
}
}
}
}
void calc(ll *f,ll *g,int n){
for(reg i=;i<n;++i){
rev[i]=(rev[i>>]>>)|((i&)?n>>:);
}
NTT(f,n,);NTT(g,n,);
for(reg i=;i<n;++i) f[i]=f[i]*g[i]%mod;
NTT(f,n,-);
ll iv=qm(n,mod-);
for(reg i=;i<n;++i) f[i]=f[i]*iv%mod;
}
void add(ll *f,ll *g,int n){//n is max(len f,len g)
for(reg i=;i<n;++i){
f[i]=(f[i]+g[i])%mod;
}
}
void sub(ll *f,ll *g,int n){
for(reg i=;i<n;++i){
f[i]=(f[i]-g[i]+mod)%mod;
}
}
void inv(ll *f,ll *g,int n){
// cout<<" inv "<<n<<endl;
if(n==){
g[]=qm(f[],mod-);return;
}
inv(f,g,n>>);
for(reg i=;i<n;++i) t[i]=f[i];
for(reg i=n;i<*n;++i) t[i]=;
for(reg i=;i<*n;++i){
rev[i]=(rev[i>>]>>)|((i&)?n:);
}
NTT(t,*n,);NTT(g,*n,);
for(reg i=;i<*n;++i){
g[i]=(+mod-t[i]*g[i]%mod)%mod*g[i]%mod;
}
NTT(g,*n,-);
ll iv=qm(*n,mod-);
for(reg i=;i<n;++i) g[i]=g[i]*iv%mod;
for(reg i=n;i<*n;++i) g[i]=;
}
void tran(ll *f,int len,int n){//warning!! bac to length=length+len
for(reg i=n-+len;i>=len;--i){
f[i]=f[i-len];
}
for(reg i=;i<len;++i) f[i]=;
}
int main(){
rd(n);
g[]=;g[]=;g[]=;g[]=;
int lp;
for(lp=;lp<=n+n+;lp<<=);//warning!! biggest length
for(reg i=;i<=n;++i){
g[i]=(g[i-]+g[i-])%mod;
}
for(reg i=;i<=n;++i){
g0[i]=g[i]*i%mod*i%mod;
g1[i]=g[i]*(i+)%mod*(i+)%mod;
g2[i]=g[i]*(i+)%mod*(i+)%mod;
}
l[]=;
// cout<<lp<<endl;
// x3g2[0]=1;
// memcpy(p,g2,sizeof g2);tran(p,3,n+1);
// sub(x3g2,p,lp);
// inv(x3g2,ix3g2,lp);
// cout<<" ix3g2 "<<endl;
// prt(ix3g2,0,lp-1); memcpy(p,g2,sizeof g2);
tran(p,,n+);
sub(l,p,lp); memcpy(p,g0,sizeof g0);
tran(p,,n+);
sub(l,p,lp); memcpy(p,g0,sizeof g0);
memcpy(q,g2,sizeof g2);
calc(p,q,lp);
tran(p,,lp);
add(l,p,lp); memcpy(p,g1,sizeof g1);
memcpy(q,g1,sizeof g1);
calc(p,q,lp);
tran(p,,lp);
sub(l,p,lp); inv(l,ni,lp);
for(reg i=n+;i<lp;++i) ni[i]=;
//////////////////////inv 1
memcpy(l,g0,sizeof g0); memcpy(p,g0,sizeof g0);
memcpy(q,g2,sizeof g2);
calc(p,q,lp);
tran(p,,lp);
sub(l,p,lp); memcpy(p,g1,sizeof g1);
memcpy(q,g1,sizeof g1);
calc(p,q,lp);
tran(p,,lp);
add(l,p,lp); for(reg i=n+;i<lp;++i) l[i]=;
calc(l,ni,lp);
memcpy(f0,l,sizeof l);
for(reg i=n+;i<lp;++i) f0[i]=;
/////////////////////f0
memset(l,,sizeof l);
l[]=;
memcpy(p,g2,sizeof g2);
tran(p,,n+);
sub(l,p,lp); memset(ni,,sizeof ni);
inv(l,ni,lp);
for(reg i=n+;i<lp;++i) ni[i]=;
// prt(ni,0,lp-1); memcpy(l,g1,sizeof g1);
memcpy(p,g1,sizeof g1);
tran(p,,n+);
// cout<<" ll "<<endl;
// prt(p,0,lp-1);
memcpy(q,f0,sizeof f0);
//prt(q,0,lp-1);
calc(p,q,lp); add(l,p,lp); for(reg i=n+;i<lp;++i) l[i]=;
memcpy(p,ni,sizeof ni);
calc(l,p,lp); memcpy(f1,l,sizeof l);
for(reg i=n+;i<lp;++i) f1[i]=;
///////////////////////f1 memcpy(l,g2,sizeof g2);
memcpy(p,g1,sizeof g1);
tran(p,,n+);
memcpy(q,f1,sizeof f1);
calc(p,q,lp);
add(l,p,lp); for(reg i=n+;i<lp;++i) l[i]=;
// memcpy(p,ni,sizeof ni);
calc(l,ni,lp); memcpy(f2,l,sizeof l);
/////////////////////f2
// cout<<"f0 "<<endl;
// for(reg i=0;i<n;++i){
// cout<<f0[i]<<" ";
// }cout<<endl;
// cout<<"f1 "<<endl;
// for(reg i=0;i<n;++i){
// cout<<f1[i]<<" ";
// }cout<<endl;
// cout<<"f2 "<<endl;
// for(reg i=0;i<n;++i){
// cout<<f2[i]<<" ";
// }cout<<endl;
ll ans=(ll)n*(g[n-]+g[n-])%mod*(n-)%mod*(n-)%mod;
for(reg i=;i<=n;++i){
ll tmp=;
tmp=(tmp+g[i-]*f0[n-i]%mod*(i-)%mod*(i-)%mod)%mod;
if(i>&&i<n) tmp=(tmp+g[i-]*f1[n-i-]%mod*%mod*(i-)%mod*(i-)%mod)%mod;
if(i>&&i<n-) tmp=(tmp+g[i-]*f2[n-i-]%mod*(i-)%mod*(i-)%mod)%mod;
tmp=tmp*(i-)%mod;
ans=(ans+tmp)%mod;
}
cout<<ans;
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/2/27 15:57:21
*/

总结:

0.拆开,只考虑一个半圆

1.由于贡献是根据割线统计的,推DP式子时候根据割线的跨越与否进行统计

CF848E Days of Floral Colours——DP+多项式求逆/分治NTT的更多相关文章

  1. BZOJ 3456: 城市规划(dp+多项式求逆)

    传送门 解题思路 这道题就是求带标号的无向连通图个数,首先考虑\(O(n^2)\)的做法,设\(f_i\)表示有\(i\)个节点的无向连通图个数,那么考虑容斥,先把所有的无向图求出,即为\(2^{C( ...

  2. 【洛谷4238】 多项式求逆(NTT,分治)

    前言 多项式求逆还是爽的一批 Solution 考虑分治求解这个问题. 直接每一次NTT一下就好了. 代码实现 #include<stdio.h> #include<stdlib.h ...

  3. 多项式求逆/分治FFT 学习笔记

    一.多项式求逆 给定一个多项式 \(F(x)\),请求出一个多项式 \(G(x)\), 满足 \(F(x) * G(x) \equiv 1 ( \mathrm{mod\:} x^n )\).系数对 \ ...

  4. 【bzoj3456】城市规划 dp+多项式求逆

    Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或 ...

  5. Luogu4238 【模板】多项式求逆(NTT)

    http://blog.miskcoo.com/2015/05/polynomial-inverse 好神啊! B(x)=B'(x)·(2-A(x)B'(x)) 注意ntt的时候防止项数溢出,即将多项 ...

  6. 洛谷P4238 【模板】多项式求逆(NTT)

    传送门 学习了一下大佬的->这里 已知多项式$A(x)$,若存在$A(x)B(x)\equiv 1\pmod{x^n}$ 则称$B(x)$为$A(x)$在模$x^n$下的逆元,记做$A^{-1} ...

  7. bzoj 3456 城市规划 多项式求逆+分治FFT

    城市规划 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1091  Solved: 629[Submit][Status][Discuss] Desc ...

  8. hdu 5730 Shell Necklace [分治fft | 多项式求逆]

    hdu 5730 Shell Necklace 题意:求递推式\(f_n = \sum_{i=1}^n a_i f_{n-i}\),模313 多么优秀的模板题 可以用分治fft,也可以多项式求逆 分治 ...

  9. BZOJ 3456: 城市规划 与 多项式求逆算法介绍(多项式求逆, dp)

    题面 求有 \(n\) 个点的无向有标号连通图个数 . \((1 \le n \le 1.3 * 10^5)\) 题解 首先考虑 dp ... 直接算可行的方案数 , 容易算重复 . 我们用总方案数减 ...

随机推荐

  1. 从零开始搭建属于你的React/redux/webpack脚手架

    大家好,我是苏南,今天要给大家分享的是<<我的react入门到放弃之路>>,当然,也不是真的放弃啦--哈哈,这篇博客原本是从17年初写的,一直没有在csdn发布,希望今天不会太 ...

  2. Session会话与Cookie简单说明

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  3. mysql操作命令梳理(1)-索引

    1.创建索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIMARY KE ...

  4. Echarts中graph类型的运用求教

    以下是百度Echarts官网上关系图的源码,但是这个关系图的node节点和edge都是静态文件里规定好的,我现在想动态实现,点击其中一个节点A然后新产生一个新节点B,并且有A和B之间的edge,就类似 ...

  5. Linux内核分析 读书笔记 (第五章)

    第五章 系统调用 5.1 与内核通信 1.调用在用户空间进程和硬件设备之间添加了一个中间层.该层主要作用有三个: 为用户空间提供了硬件的抽象接口. 系统调用保证了系统的稳定和安全. 实现多任务和虚拟内 ...

  6. redis的优缺点

    优点: 1 读写性能优异 2 支持数据持久化,支持AOF和RDB两种持久化方式 3 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离. 4 数据结构丰富:除了支持string类型的value ...

  7. git学习笔记2——ProGit2

    先附上教程--<ProGit 2> 配置信息 Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量. 这些变量存储在三个不同的位置: /etc/git ...

  8. PAT 1081 检查密码

    https://pintia.cn/problem-sets/994805260223102976/problems/994805261217153024 本题要求你帮助某网站的用户注册模块写一个密码 ...

  9. Eclipse集成Tomcat报错:java.lang.OutOfMemoryError: PermGen space

    Eclipse集成Tomcat报错,使用Spring 4.3 框架,运行一段应用后,控制台报错: Unexpected death of background thread ContainerBack ...

  10. node的consoidate的插件统一

    使用consolidate.ejs.的这种形式. let express = require('express'); let app = express(); app.set('views','返回的 ...