[BZOJ 3456]城市规划(cdq分治+FFT)

题面

求有标号n个点无向连通图数目.

分析

设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量。

显然\(g(i)=2^{C_i^2}\)种,但是我们要把不联通的去掉。

枚举1号点所在联通块大小\(j\).从剩下\(i-1\)个点里选\(j-1\)个点和1号点构成联通块,有\(C_{i-1}^{j-1}\)种选法.1号点所在联通块的连边方案有\(f(i)\)种,剩下\(i-j\)个点随便连边,有\(g(i-j)\)种

那么$$f(i)=g(i)-\sum_{j=1}^{i-1} C_{i-1}^{j-1} f(j)g(i-j)$$

把式子展开:

\[\begin{aligned} f(i) &= g(i)-\sum_{j=1}^{i-1} \frac{(i-1)!}{(i-j)!(j-1)!} f(j)g(i-j) \\ \frac{f(i)}{(i-1)!}&=\frac{g(i)}{(i-1)!}-\sum_{j=1}^{i-1} \frac{f(j)}{(j-1)!} \cdot \frac{g(i-j)}{(i-j)!}\end{aligned}
\]

令\(A(i)=\frac{f(i)}{(i-1)!},B(i)=\frac{g(i)}{i!},C(i)=\frac{g(i)}{(i-1)!}\)

那么$$A(i)=C(i)-\sum_{j=1}^{i-1} A(j) B(i-j)$$

右边可以分治FFT。


分治FFT的思路:

分治FFT的一般形式:

已知多项式\(g\),且有$f(i)=\sum_{j=1}^if(i-j)g(j),f(0)=1 \(,求\)f$

但是这里卷积内有一个f,f是未知的,就不能用常规的多项式乘法了。

我们可以引入cdq分治。假设我们在分治求\(f[l...r]\),已经求出了\(f[l...mid]\),只需要计算区间\([l,mid]\)对区间\([mid+1,r]\)的贡献.

考虑\(x \in [mid+1,r]\),\(f(x) = \sum _{i = 1} ^ {x} f(i) * g(x - i)\)

注意到\([1,l]\)部分的贡献在之前的分治过程里已经计算过,不管。\(f[mid+1,r]\)还没有计算,暂且设为0.那左半边区间的贡献就是

\[\begin{aligned}
f(x)
&= \sum _ {i = L} ^ {x} f(i)g(x - i) \\
&= \sum _ {i = 0} ^ {x - L} f(i + L) g(x - L - i)
\end{aligned}\]

那么我们可以把f的[l,mid]项拿出来,其他项置0,在把这个和g的[0,r−l]卷起来就可以得到贡献,然后加到f上就好了。

void cdq_divide(ll *f,ll *g,int l,int r){
static ll tmpa[maxn+5],tmpb[maxn+5];
if(l==r) return;
int mid=(l+r)>>1;
cdq_divide(f,g,l,mid);
int tn=1,k=0;
while(tn<r-l){
k++;
tn*=2;
}
for(int i=0;i<tn;i++) tmpa[i]=tmpb[i]=0;
for(int i=l;i<=mid;i++) tmpa[i-l]=f[i];
for(int i=1;i<=r-l;i++) tmpb[i-1]=g[i];
mul(tmpa,tmpb,tmpa,tn);
for(int i=mid+1;i<=r;i++) f[i]=(f[i]+tmpa[i-l-1])%mod;//注意第x项实际上是第x-l-1项
cdq_divide(f,g,mid+1,r);
}

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 300000
#define G 3
#define invG 334845270
#define inv2 499122177
#define mod 1004535809
using namespace std;
typedef long long ll;
inline ll fast_pow(ll x,ll k){
ll ans=1;
while(k){
if(k&1) ans=ans*x%mod;
x=x*x%mod;
k>>=1;
}
return ans;
}
inline ll inv(ll x){
return fast_pow(x,mod-2);
} void NTT(ll *x,int n,int type){
static int rev[maxn+5];
int tn=1;
int k=0;
while(tn<n){
tn*=2;
k++;
}
for(int i=0;i<tn;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
for(int i=0;i<n;i++){
if(i<rev[i]) swap(x[i],x[rev[i]]);
}
for(int len=1;len<n;len*=2){
int sz=len*2;
ll gn1=fast_pow((type==1?G:invG),(mod-1)/sz);
for(int l=0;l<n;l+=sz){
int r=l+len-1;
ll gnk=1;
for(int i=l;i<=r;i++){
ll tmp=x[i+len];
x[i+len]=(x[i]-gnk*tmp%mod+mod)%mod;
x[i]=(x[i]+gnk*tmp%mod)%mod;
gnk=gnk*gn1%mod;
}
}
}
if(type==-1){
int invsz=inv(n);
for(int i=0;i<n;i++) x[i]=x[i]*invsz%mod;
}
}
void mul(ll *a,ll *b,ll *ans,int sz){
NTT(a,sz,1);
NTT(b,sz,1);
for(int i=0;i<sz;i++) ans[i]=a[i]*b[i]%mod;
NTT(ans,sz,-1);
} void cdq_divide(ll *f,ll *g,int l,int r){
static ll tmpa[maxn+5],tmpb[maxn+5];
if(l==r) return;
int mid=(l+r)>>1;
cdq_divide(f,g,l,mid);
int tn=1,k=0;
while(tn<r-l){
k++;
tn*=2;
}
for(int i=0;i<tn;i++) tmpa[i]=tmpb[i]=0;
for(int i=l;i<=mid;i++) tmpa[i-l]=f[i];
for(int i=1;i<=r-l;i++) tmpb[i-1]=g[i];
mul(tmpa,tmpb,tmpa,tn);
for(int i=mid+1;i<=r;i++) f[i]=(f[i]-tmpa[i-l-1]+mod)%mod;
cdq_divide(f,g,mid+1,r);
} int n;
ll f[maxn+5],g[maxn+5];
ll fact[maxn+5];
ll invfact[maxn+5];
ll get_g(ll n){
return fast_pow(2,n*(n-1)/2);
}
void ini(int n){
fact[0]=1;
for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
invfact[n]=inv(fact[n]);
for(int i=n-1;i>=0;i--) invfact[i]=invfact[i+1]*(i+1)%mod;
}
int main(){
// printf("%lld\n",inv(3));
scanf("%d",&n);
ini(n);
int tn=1;
for(int i=1;i<=n;i++) f[i]=get_g(i)*invfact[i-1]%mod; //初始值C(i)
for(int i=1;i<=n;i++) g[i]=get_g(i)*invfact[i]%mod;
while(tn<=n) tn*=2;
cdq_divide(f,g,0,tn-1);
// for(int i=0;i<n;i++) printf("%lld ",f[i]);
printf("%lld\n",f[n]*fact[n-1]%mod);
}

[BZOJ 3456]城市规划(cdq分治+FFT)的更多相关文章

  1. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

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

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

  3. HDU - 5730 :Shell Necklace(CDQ分治+FFT)

    Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n b ...

  4. [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)

    [BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...

  5. bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...

  6. bzoj 3456 城市规划 —— 分治FFT / 多项式求逆 / 指数型生成函数(多项式求ln)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 首先考虑DP做法,正难则反,考虑所有情况减去不连通的情况: 而不连通的情况就是那个经典 ...

  7. BNUOJ 51279[组队活动 Large](cdq分治+FFT)

    传送门 大意:ACM校队一共有n名队员,从1到n标号,现在n名队员要组成若干支队伍,每支队伍至多有m名队员,求一共有多少种不同的组队方案.两个组队方案被视为不同的,当且仅当存在至少一名队员在两种方案中 ...

  8. HDU 5730 Shell Necklace cdq分治+FFT

    题意:一段长为 i 的项链有 a[i] 种装饰方式,问长度为n的相连共有多少种装饰方式 分析:采用dp做法,dp[i]=∑dp[j]*a[i-j]+a[i],(1<=j<=i-1) 然后对 ...

  9. HDU 5730 Shell Necklace(CDQ分治+FFT)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...

随机推荐

  1. 20180804 excel规划求解。。。

    把一个已经变量更出数据去求解

  2. 容器内安装nvidia,cuda,cudnn

    /var/lib/docker/overlay2 占用很大,清理Docker占用的磁盘空间,迁移 /var/lib/docker 目录 du -hs /var/lib/docker/ 命令查看磁盘使用 ...

  3. grpc:gRPC Concepts

    本文介绍一些主要的gRPC概念. 服务定义 gRPC支持4种方法: 1.Unary RPCs where the client sends a single request to the server ...

  4. [业务监控系统]MEDIVH架构设计和接入方案

    Medivh监控系统- 系统介绍 本系统旨在提供业务监控实时数据和历史数据以及报表.阈值报警.同比增长分析等一体化的历史业务数据解决方案. 技术选型 sdk部门有C#版和java版,api和websi ...

  5. Tire树简介

    又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种. 典型应用:用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 它的优点是:利用字符串的公共 ...

  6. 更好的构建 Node 服务的工具

    更好的构建 Node 服务的工具 无论前端项目在打包后都发送给后台, 有时候自己想看看效果在运行 npm run build 后只是看到一个 build 文件夹,但是直接打开是无法浏览,因此需要开启一 ...

  7. [BZOJ1697][USACO2007 FEB]Cow Sorting牛排序:贪心+置换

    分析 一个月前做的一道题补一下题解,就简单写一写吧. 单独考虑每一个循环节,如果只进行内部的调整,最优方案显然是把最小的绕这个循环交换一圈. 但是借助全局最小值可能使答案更优,两种情况取个\(\max ...

  8. 1.WIN10下搭建vue开发环境

    WIN10下搭建vue开发环境 详细的安装步骤如下: 一.安装node.js 说明:安装node.js的windows版本后,会自动安装好node以及包管理工具npm,我们后续的安装将依赖npm工具. ...

  9. CDH搭建和集成spark、kafka操作

    系统:Centos7 CDH版本:5.14.0 请自己提前安装好:mysql.jdk 并下载好相关依赖(每一台机器) yum -y install chkconfig python bind-util ...

  10. 【Python】Python读取文件报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0x99 in position 20: illegal multibyte sequence

    环境描述 text.txt 今天的天气不错 是个皻的选择 读取文件的代码 #!/usr/bin/python #-*- coding:UTF-8 -*- f = open(r'D:\Python\Py ...