官方题解:
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. (7)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 利用Polly+AOP+依赖注入封装的降级框架

    创建简单的熔断降级框架 要达到的目标是: 参与降级的方法参数要一样,当HelloAsync执行出错的时候执行HelloFallBackAsync方法. public class Person { [H ...

  2. U盘、移动硬盘等弹出 “文件或目录损坏且无法读取” 实测解决办法

    U盘跟其他的机器一样,使用久了难免会出故障,比如常见的弹出一个文件或目录损坏且无法读取的对话框,吓你一跳,整个U盘都损坏的意思,那里面的资料怎么办呢,所以很多人很着急,其实遇到这种情况一般都是之前使用 ...

  3. linux下用户操作记录审计环境的部署记录

    通常,我们运维管理人员需要知道一台服务器上有哪些用户登录过,在服务器上执行了哪些命令,干了哪些事情,这就要求记录服务器上所用登录用户的操作信息,这对于安全维护来说很有必要.废话不多说了,下面直接记录做 ...

  4. mysql操作命令梳理(2)-alter(update、insert)

    在mysql运维操作中会经常使用到alter这个修改表的命令,alter tables允许修改一个现有表的结构,比如增加或删除列.创造或消去索引.改变现有列的类型.或重新命名列或表本身,也能改变表的注 ...

  5. 浏览器跨域请求之credentials

    -时间起源- 前段时间,需要弄个简单的网站出来,访问远程的api服务. 我是这么做的.首先是在搭建一个nodejs服务来运行前端页面.在我请求登录的时候,能成功返回相应的成功信息.然后,当我再次请求读 ...

  6. B. Vasya and Isolated Vertices

    链接 [http://codeforces.com/contest/1065/problem/B] 题意 给你n个点,m条边,让你找最多孤立点和最少孤立点,不能有自环路 分析 对于最少max(0,n- ...

  7. 【个人项目总结】C#四则运算表达式生成程序

    S1&2.个人项目时间估算 PSP表格如下: PSP2.1 Personal Software Process Stages Time(Before) Time(After) Planning ...

  8. SQLserver 进程被死锁问题解决

    事务(进程ID xx)与另一个进程被死锁在 锁|通信缓冲区 资源上,并且已被选座死锁牺牲品.请重新运行该事务.Sqlserver 当出现这个错误时,如下图: 解决办法:更改数据库事务隔离级别 alte ...

  9. chrome启用flash不询问

    69版本之后 打开 chrome://flags/#enable-ephemeral-flash-permission 把它从Default改为Disabled 重新打开Chrome,进入 chrom ...

  10. opencv学习笔记(四)

    ROI---设定感兴趣的区域(region of interest) 定义: Mat imageROI; //方法一:通过Rect指定矩形区域 imageROI=image(Rect(500,250, ...