官方题解:
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. C/C++中int128的那点事

    最近群友对int128这个东西讨论的热火朝天的.讲道理的话,编译器的gcc是不支持__int128这种数据类型的,比如在codeblocks 16.01/Dev C++是无法编译的,但是提交到大部分O ...

  2. BugkuCTF web基础$_GET

    前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...

  3. TRIO-basic指令--FLEXLINK

    Type: Axis Command Syntax: FLEXLINK(base_dist, excite_dist, link_dist, base_in, base_out, excite_acc ...

  4. Steamworks上传游戏

    1.在steamPipe下配置Depot,每个Depot表示程序对应的分支配置语言,操作系统,架构组合等 2.安装,启动项目是配置游戏启动文件的相关信息,不同的操作系统架构等需要添加不同的启动项 3. ...

  5. Linux下部署SSH登录时的二次身份验证环境记录(利用Google Authenticator)

    一般来说,使用ssh远程登录服务器,只需要输入账号和密码,显然这种方式不是很安全.为了安全着想,可以使用GoogleAuthenticator(谷歌身份验证器),以便在账号和密码之间再增加一个验证码, ...

  6. 个人博客-week7

    团队任务收获及个人感想 团队任务已经进行了一个多月的时间,我很荣幸能和软剑攻城队的小伙伴们度过这一个月的开发时光.在这一个月的时间里,我亲身经历了一个软件从想法到实现,从创意到实体的过程.同时我也在和 ...

  7. .NET组件介绍系列

    一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)http://www.cnblogs.com/pengze0902/p/6122311.html 高效而稳定的企业级.NET Offi ...

  8. Python学习笔记 -- 第四章

    高阶函数 变量可以指向函数 f=abs f(-10) 10 变量f指向abs函数,直接调用abs()函数和调用f()完全相同 传入参数 变量可以指向函数,函数的参数可以接收另一个函数的参数,这种函数成 ...

  9. Linux虚拟机下与主机通信

    1.更改虚拟机ip和主机ip同一网段 2.配置虚拟机的网络适配器 3.主机进行ping测试

  10. Java abstract interface与 interface的区别

    我们常常遇到abstract class与 interface的区别,今天却遇到了abstract interface,感觉interface不用abstract再修饰了啊.结论:事实也确实如此,编译 ...