Luogu4233 射命丸文的笔记 DP、多项式求逆
注意到总共有\(\frac{n!}{n}\)条本质不同的哈密顿回路,每一条哈密顿回路恰好会出现在\(2^{\binom{n}{2} - n}\)个图中,所以我们实际上要算的是强连通有向竞赛图的数量。
设\(f_i\)表示点数为\(i\)的强连通竞赛图数,转移考虑用总数\(2^\binom{i}{2}\)减去不强连通的图数量。如果竞赛图不强连通,我们可以枚举拓扑序最靠后的一个强连通子图,如果它的大小为\(j\),那么剩下\(i-j\)个点之间的边可以任意连,但是这\(i-j\)个和这\(j\)个点之间的边的方向是确定的,可以得到转移\(f_i = 2^\binom{i}{2} - \sum\limits_{j=1}^{i-1} \binom{i}{j} 2^\binom{i-j}{2} f_j\),直接做复杂度\(O(n^2)\)
然后考虑优化。把\(\binom{i}{j}\)拆开然后左右两边各除以\(i!\)得到\(\frac{f_i}{i!} = \frac{2^\binom{i}{2}}{i!} - \sum\limits_{j=1}^{i-1} \frac{f_j}{j!} \frac{2^\binom{i-j}{2}}{i-j!}\)。设多项式\(F = \sum\limits_{i=1}^n \frac{f_i}{i!}x^i\),\(G = \sum\limits_{i=1}^n \frac{2^\binom{i}{2}}{i!} x^i\),可以得到\(F = G - F * G\),即\(F = \frac{G}{G + 1}\),多项式求逆即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<cassert>
//This code is written by Itst
using namespace std;
#define int long long
const int MOD = 998244353 , _ = (1 << 18) + 3;
int jc[_] , inv[_] , G[_] , H[_] , N;
#define ch2(x) ((x) * ((x) - 1) / 2)
int poww(int a , int b){
int tms = 1;
while(b){
if(b & 1) tms = tms * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return tms;
}
namespace poly{
const int G = 3 , INV = 332748118;
int dir[_] , need , invnd;
void init(int len){
need = 1;
while(need < len) need <<= 1;
invnd = poww(need , MOD - 2);
for(int i = 1 ; i < need ; ++i)
dir[i] = (dir[i >> 1] >> 1) | (i & 1 ? need >> 1 : 0);
}
void NTT(int *arr , int tp){
for(int i = 1 ; i < need ; ++i)
if(i < dir[i])
arr[i] ^= arr[dir[i]] ^= arr[i] ^= arr[dir[i]];
for(int i = 1 ; i < need ; i <<= 1){
int wn = poww(tp == 1 ? G : INV , MOD / i / 2);
for(int j = 0 ; j < need ; j += i << 1){
int w = 1;
for(int k = 0 ; k < i ; ++k , w = w * wn % MOD){
int x = arr[j + k] , y = arr[i + j + k] * w % MOD;
arr[j + k] = x + y >= MOD ? x + y - MOD : x + y;
arr[i + j + k] = x < y ? x + MOD - y : x - y;
}
}
}
if(tp != 1)
for(int i = 0 ; i < need ; ++i)
arr[i] = arr[i] * invnd % MOD;
}
#define clr(x) memset(x , 0 , sizeof(int) * need)
int A[_] , B[_];
void getInv(int *a , int *b , int len){
if(len == 1) return (void)(b[0] = poww(a[0] , MOD - 2));
getInv(a , b , (len + 1) >> 1);
memcpy(A , a , sizeof(int) * len);
memcpy(B , b , sizeof(int) * len);
init(len * 2 + 3); NTT(A , 1); NTT(B , 1);
for(int i = 0 ; i < need ; ++i)
A[i] = A[i] * B[i] % MOD * B[i] % MOD;
NTT(A , -1);
for(int i = 0 ; i < len ; ++i)
b[i] = (2 * b[i] - A[i] + MOD) % MOD;
clr(A); clr(B);
}
}
signed main(){
cin >> N;
jc[0] = 1;
for(int i = 1 ; i <= N ; ++i) jc[i] = jc[i - 1] * i % MOD;
inv[N] = poww(jc[N] , MOD - 2);
for(int i = N - 1 ; i >= 0 ; --i) inv[i] = inv[i + 1] * (i + 1) % MOD;
for(int i = 1 ; i <= N ; ++i) G[i] = 1ll * poww(2 , ch2(i)) * inv[i] % MOD;
G[0] = 1; poly::getInv(G , H , N + 1); G[0] = 0;
poly::init(2 * N + 2); poly::NTT(G , 1); poly::NTT(H , 1);
for(int i = 0 ; i < poly::need ; ++i)
G[i] = 1ll * G[i] * H[i] % MOD;
poly::NTT(G , -1);
for(int i = 1 ; i <= N ; ++i)
printf("%d\n" , i == 1 ? 1 : (i == 2 ? -1 : poww(G[i] , MOD - 2) * inv[i] % MOD * jc[i - 1] % MOD * poww(2 , ch2(i) - i) % MOD));
return 0;
}
Luogu4233 射命丸文的笔记 DP、多项式求逆的更多相关文章
- 洛谷P4233 射命丸文的笔记 【多项式求逆】
题目链接 洛谷P4233 题解 我们只需求出总的哈密顿回路个数和总的强联通竞赛图个数 对于每条哈密顿回路,我们统计其贡献 一条哈密顿回路就是一个圆排列,有\(\frac{n!}{n}\)种,剩余边随便 ...
- CF848E Days of Floral Colours——DP+多项式求逆/分治NTT
官方题解:http://codeforces.com/blog/entry/54233 就是由简入繁 1.序列处理,只考虑一个半圆 2.环形处理(其实这个就是多了旋转同构) 然后基于分割线邻居的跨越与 ...
- BZOJ 3456: 城市规划(dp+多项式求逆)
传送门 解题思路 这道题就是求带标号的无向连通图个数,首先考虑\(O(n^2)\)的做法,设\(f_i\)表示有\(i\)个节点的无向连通图个数,那么考虑容斥,先把所有的无向图求出,即为\(2^{C( ...
- 【bzoj3456】城市规划 dp+多项式求逆
Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或 ...
- BZOJ 3456: 城市规划 与 多项式求逆算法介绍(多项式求逆, dp)
题面 求有 \(n\) 个点的无向有标号连通图个数 . \((1 \le n \le 1.3 * 10^5)\) 题解 首先考虑 dp ... 直接算可行的方案数 , 容易算重复 . 我们用总方案数减 ...
- 【bzoj3456】城市规划(多项式求逆+dp)
Description 求\(~n~\)个点组成的有标号无向连通图的个数.\(~1 \leq n \leq 13 \times 10 ^ 4~\). Solution 这道题的弱化版是poj1737, ...
- [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)
[BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...
- 多项式求逆/分治FFT 学习笔记
一.多项式求逆 给定一个多项式 \(F(x)\),请求出一个多项式 \(G(x)\), 满足 \(F(x) * G(x) \equiv 1 ( \mathrm{mod\:} x^n )\).系数对 \ ...
- [BZOJ3456]城市规划:DP+NTT+多项式求逆
写在前面的话 昨天听吕老板讲课,数数题感觉十分的神仙. 于是,ErkkiErkko这个小蒟蒻也要去学数数题了. 分析 Miskcoo orz 带标号无向连通图计数. \(f(x)\)表示\(x\)个点 ...
随机推荐
- 干货 | 10分钟带你掌握branch and price(分支定价)算法超详细原理解析
00 前言 相信大家对branch and price的神秘之处也非常好奇了.今天我们一起来揭秘该算法原理过程.不过,在此之前,请大家确保自己的branch and bound和column gene ...
- kubernetes监控终极方案-kube-promethues
kube-promethues简介 前面我们学习了Heapster+cAdvisor方式监控,这是Prometheus Operator出现之前的k8s监控方案.后来出现了Prometheus Ope ...
- python安装redis库
pip install redis 没有相应的资源 可以到redisio上找到clients, https://redis.io/clients 如下所示 下图中带黄五角星的为官方推荐的: 下 ...
- how does SELECT TOP works when no order by is specified?
how does SELECT TOP works when no order by is specified? There is no guarantee which two rows you ge ...
- (8)Flask微电影项目会员中心其他页面搭建
会员中心修改密码.评论.登录日志和收藏电影4个页面的内容. 一.修改密码页面: {% extends "home/home.html" %} {% block css %} < ...
- Python3基础 dict __len__ 统计键值对的数量
Python : 3.7.3 OS : Ubuntu 18.04.2 LTS IDE : pycharm-community-2019.1.3 ...
- Jmeter多业务混合场景如何设置各业务所占并发比例
在进行多业务混合场景测试中,需要分配每个场景占比. 具体有两种方式: 1.多线程组方式: 2.逻辑控制器控制: 第一种: jmeter一个测试计划可以添加多个线程组,我们把不同的业务放在不同的线程组中 ...
- (转)SQLAlchemy入门和进阶
URL:https://zhuanlan.zhihu.com/p/27400862 https://www.cnblogs.com/mrchige/p/6389588.html---SQLAlchem ...
- Hadoop,Spark,Flink 相关KB
Hive: https://stackoverflow.com/questions/17038414/difference-between-hive-internal-tables-and-exter ...
- Nginx 反向代理 一个IP代理多个域名,不区分端口,类似windows虚拟机。
简介: IP有限,所以我们以前使用端口来区分不同的虚拟主机,提供不同的WEB服务. 小范围还凑活,一旦规模扩大,地址记不住了吧?端口记不住了吧? 这个时候我们可以使用DNS,域名解析,毕竟记名字比记I ...