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\)个点 ...
随机推荐
- P4936 题解
\(\text{Update}\)(2019.10.05): 递推公式推法更详细: 通项公式更新详细版: 单位矩阵的推法更加详细. 特别鸣谢 @Smallbasic 苣佬,是他教会了我推递推公式和通项 ...
- Vector(动态数组)怎么用咧↓↓↓
定义方式:vector<int> a; //二维vector<int>a[100] 在末尾压入容器:a.push_back(x);//二维 a[i].push_back(x) ...
- DDL 语言
数据库模式定义语言并非程序设计语言,DDL数据库模式定义语言是SQL语言(结构化查询语言)的组成部分. SQL语言包括四种主要程序设计语言类别的语句:数据定义语言(DDL),数据操作语言(DML),数 ...
- MySQL 自动插入、更新时间戳
在 MySql 中,要做到自动出入当前时间戳,只要在定义表格时将字段的默认值设置为 CURRENT_TIMESTAMP 即可. 如: create table if not exists my_tab ...
- TCP/IP协议栈中的TimeStamp选项
原文转自:http://www.cnblogs.com/lovemyspring/articles/4271716.html TCP应该是以太网协议族中被应用最为广泛的协议之一,这里就聊一聊TCP协议 ...
- nginx针对某个url限制ip访问,常用于后台访问限制【转】
假如我的站点后台地址为: http://www.abc.net/admin.php 那么我想限制只有个别ip可以访问后台,那么需要在配置文件中增加: location ~ .*admin.* { al ...
- GIS地理工具案例教程——批量合并影像-批量镶嵌栅格
GIS地理工具案例教程--批量合并影像-批量镶嵌栅格 商务合作,科技咨询,版权转让:向日葵,135-4855__4328,xiexiaokui#qq.com 关键词:批量.迭代.循环.自动.智能.地理 ...
- CORS-跨域问题:Access-Control-Allow-Origin Header and the ASP.NET Web API
代码控制跨域: 如何使用:在 Global.asax 对应的控制类中: protected void Application_BeginRequest() { if (CorsFilter.IsOpt ...
- PLSQL查询执行计划
转: PLSQL查询执行计划 01(转) 2019-05-15 15:15:43 p享自由q 阅读数 365 一般优化途径: 如果能通过修改语句优化,比如查询条件或执行顺序,sql改不了,可以通过 ...
- [LeetCode] 121. Best Time to Buy and Sell Stock 买卖股票的最佳时间
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...