CF848E Days of Floral Colours——DP+多项式求逆/分治NTT
官方题解:
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的更多相关文章
- BZOJ 3456: 城市规划(dp+多项式求逆)
传送门 解题思路 这道题就是求带标号的无向连通图个数,首先考虑\(O(n^2)\)的做法,设\(f_i\)表示有\(i\)个节点的无向连通图个数,那么考虑容斥,先把所有的无向图求出,即为\(2^{C( ...
- 【洛谷4238】 多项式求逆(NTT,分治)
前言 多项式求逆还是爽的一批 Solution 考虑分治求解这个问题. 直接每一次NTT一下就好了. 代码实现 #include<stdio.h> #include<stdlib.h ...
- 多项式求逆/分治FFT 学习笔记
一.多项式求逆 给定一个多项式 \(F(x)\),请求出一个多项式 \(G(x)\), 满足 \(F(x) * G(x) \equiv 1 ( \mathrm{mod\:} x^n )\).系数对 \ ...
- 【bzoj3456】城市规划 dp+多项式求逆
Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或 ...
- Luogu4238 【模板】多项式求逆(NTT)
http://blog.miskcoo.com/2015/05/polynomial-inverse 好神啊! B(x)=B'(x)·(2-A(x)B'(x)) 注意ntt的时候防止项数溢出,即将多项 ...
- 洛谷P4238 【模板】多项式求逆(NTT)
传送门 学习了一下大佬的->这里 已知多项式$A(x)$,若存在$A(x)B(x)\equiv 1\pmod{x^n}$ 则称$B(x)$为$A(x)$在模$x^n$下的逆元,记做$A^{-1} ...
- bzoj 3456 城市规划 多项式求逆+分治FFT
城市规划 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1091 Solved: 629[Submit][Status][Discuss] Desc ...
- hdu 5730 Shell Necklace [分治fft | 多项式求逆]
hdu 5730 Shell Necklace 题意:求递推式\(f_n = \sum_{i=1}^n a_i f_{n-i}\),模313 多么优秀的模板题 可以用分治fft,也可以多项式求逆 分治 ...
- BZOJ 3456: 城市规划 与 多项式求逆算法介绍(多项式求逆, dp)
题面 求有 \(n\) 个点的无向有标号连通图个数 . \((1 \le n \le 1.3 * 10^5)\) 题解 首先考虑 dp ... 直接算可行的方案数 , 容易算重复 . 我们用总方案数减 ...
随机推荐
- PAT 1038 统计同成绩学生
https://pintia.cn/problem-sets/994805260223102976/problems/994805284092887040 本题要求读入N名学生的成绩,将获得某一给定分 ...
- Using Android Phone to recover SD card formatted with DD command under linux
Using Android Phone to recover SD card formatted with DD command under linux 1. Formatted a sd card ...
- TestNG—学习笔记2
关于TestNG,也是一边学一边总结,对于TestNG和Junit的比较其实也没有什么意义,都是一种测试框架,都是为了应用而生的东西,没有必要说谁好谁不好了.用的熟练用的好就是真的好啊. 下面简单的总 ...
- 面象对象设计原则之二:开放封闭原则(Open-Closed Principle, OCP)
开闭原则是面向对象的可复用设计的第一块基石,它是最重要的面向对象设计原则.开闭原则由Bertrand Meyer于1988年提出,其定义如下: 开闭原则(Open-Closed Principle, ...
- taskService 流程任务组件
act_ru_task:任务表act_ru_identitylink:权限表(流程定义和用户组(用户)之间的权限数据)act_ru_variable:参数表act_hi_attachment:任务附件 ...
- php 文件上传 $_FILES 错误码
假设文件上传字段的名称file_name,则: $_FILES['file_name']['error']有以下几种类型 1.UPLOAD_ERR_OK 其值为 0,没有错误发生,文件上传成功. 2. ...
- [转帖]从 2G 到 5G,手机上网话语权的三次改变
从 2G 到 5G,手机上网话语权的三次改变 美国第一大电信运营商 Verizon 公司的 CEO Hans Vestberg 手持一部 iPad,屏幕上显示俯瞰地面的飞行地图.400 多公里外的洛杉 ...
- 软件开的目录规范+sys,os,time模块
—————————————————————————————————————————————————————————————————— start.py import sys,os # print(__ ...
- SpringMVC @SessionAttributes 使用
@SessionAttributes 只能作用在类上,作用是将指定的Model中的键值对添加至session中,方便在下一次请求中使用. 简单示例 目标是通过 @SessionAttributes 注 ...
- hdu 5919 Sequence II (可持久化线段树)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919 大致题意: 给你一个长度为n的序列,q个询问,每次询问是给你两个数x,y,经过与上一次的答案进行运算 ...