ZOJ 3874 Permutation Graph 分治NTT
Permutation Graph
Time Limit: 2 Seconds Memory Limit: 65536 KB
Edward has a permutation {a1, a2, … an}. He finds that if he connects each pair (ai, aj) such that i < j and ai > aj, he will get a graph.
For example, if the permutation is {2, 3, 1, 4}, then 1 and 2 are connected and 1 and 3 are connected.
Edward lost his permutation, but he does know the connected components of the corresponding graph. He wants to know how many permutations will result in the same connected components.
Note that two vertices u, v belong to the same connected component if there exists a sequence of vertices starting with u and ending with v such that every two subsequent vertices in the sequence are connected by an edge.
Input
There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:
The first line contains two integers n, m (1 ≤ m ≤ n ≤ 100000), indicating the length of the permutation and the number of connected components in the graph.
Each of the following m lines contains an integer ci which denotes the size of i-th connected component, followed by ci distinct integers vi,1, vi,2, … vi,ci which denotes the connected component (1 ≤ ci, vi,1, vi,2, … vi,ci ≤ n).
It is guaranteed that every number will appear in exact one connected component and c1 + c2 + … + cm = n.
Output
For each case, output the answer modulo 786433.
Sample Input
2
4 4
1 1
1 2
1 3
1 4
4 2
3 1 2 3
1 4
Sample Output
1
3
Hint
For the second case, the three permutations is: {2, 3, 1, 4}, {3, 2, 1, 4}, {3, 1, 2, 4}.
题解:
一个联通块的点必须是连续的
构造一个dp方程,令dp[i] 表示 i 个连续的点,能形成联通块的 方案数
那么 : dp[i] = n! - i*dp[n - i] 这里 i 取遍1~n-1
发现 i * dp[n-i], 就是卷积,取的模又是 费马素数, 那就NTT求解了
还要用cdq分治优化下
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 1e6+, M = 1e3+,inf = 2e9,mod = ; const LL G = , P = ; LL mul(LL x,LL y){
return (x*y-(LL)(x/(long double)P*y+1e-)*P+P)%P;
}
LL qpow(LL x,LL k,LL p){
LL ret=;
while(k){
if(k&) ret=mul(ret,x);
k>>=;
x=mul(x,x);
}
return ret;
}
LL wn[];
void getwn(){
for(int i=; i<=; ++i){
int t=<<i;
wn[i]=qpow(G,(P-)/t,P);
}
}int len;
void NTT_init() {
getwn();
} void NTT(LL y[],int op){
for(int i=,j=len>>,k; i<len-; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>;
while(j>=k){
j-=k;
k>>=;
}
if(j<k) j+=k;
}
int id=;
for(int h=; h<=len; h<<=) {
++id;
for(int i=; i<len; i+=h){
LL w=;
for(int j=i; j<i+(h>>); ++j){
LL u=y[j],t=mul(y[j+h/],w);
y[j]=u+t;
if(y[j]>=P) y[j]-=P;
y[j+h/]=u-t+P;
if(y[j+h/]>=P) y[j+h/]-=P;
w=mul(w,wn[id]);
}
}
}
if(op==-){
for(int i=; i<len/; ++i) swap(y[i],y[len-i]);
LL inv=qpow(len,P-,P);
for(int i=; i<len; ++i) y[i]=mul(y[i],inv);
}
} int T,n,m;
LL y[N],yy[N],dp[N],f[N];
void cdq(int ll,int rr) {
if(ll == rr) return ;
cdq(ll,mid);
len = ;
while(len <= rr-ll+) len<<=;
for(int i = ; i < mid-ll+; ++i) y[i] = dp[ll+i];
for(int i = mid-ll+; i < len; ++i) y[i] = ;
for(int i = ; i < len; ++i) yy[i] = f[i+];
NTT(y,),NTT(yy,);
for(int i = ; i < len; ++i) y[i] = (y[i] * yy[i])%P;
NTT(y,-);
for(int i = mid; i < rr; ++i)
dp[i+] = ((dp[i+] - y[i - ll])%mod + mod) % mod;
cdq(mid+,rr);
}
int main() {
NTT_init();
f[] = ;
for(int i = ; i <= ; ++i) {
f[i] = 1LL* f[i-] * i % mod;
dp[i] = f[i];
}
cdq(,);
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&m);
int ans = ;
for(int i = ; i <= m; ++i) {
int x,y,mi = inf,mx = ;
scanf("%d",&x);
ans = (ans * dp[x]) % mod;
for(int j = ; j <= x; ++j) {
scanf("%d",&y);
mx = max(mx,y);
mi = min(mi,y);
}
if(mx - mi + != x) ans = ;
}
printf("%d\n",ans);
}
return ;
}
ZOJ 3874 Permutation Graph 分治NTT的更多相关文章
- ZOJ 3874 Permutation Graph (分治NTT优化DP)
题面:vjudge传送门 ZOJ传送门 题目大意:给你一个排列,如果两个数构成了逆序对,就在他们之间连一条无向边,这样很多数会构成一个联通块.现在给出联通块内点的编号,求所有可能的排列数 推来推去容易 ...
- ZOJ 3874 Permutation Graph ——分治 NTT
发现每一块一定是按照一定的顺序的. 然后与标号无关,并且相同大小的对答案的影响相同. 然后列出递推式,上NTT+分治就可以了. 然后就可以与输入同阶处理答案了. #include <map> ...
- ZOJ3874 Permutation Graph 【分治NTT】
题目链接 ZOJ3874 题意简述: 在一个序列中,两点间如果有边,当且仅当两点为逆序对 给定一个序列的联通情况,求方案数对\(786433\)取模 题解 自己弄了一个晚上终于弄出来了 首先\(yy\ ...
- ZOJ3874 Permutation Graph
Time Limit: 2 Seconds Memory Limit: 65536 KB Edward has a permutation {a1, a2, … an}. He finds ...
- [gdoi2018 day1]小学生图论题【分治NTT】
正题 题目大意 一张随机的\(n\)个点的竞赛图,给出它的\(m\)条相互无交简单路径,求这张竞赛图的期望强联通分量个数. \(1\leq n,m\leq 10^5\) 解题思路 先考虑\(m=0\) ...
- #565. 「LibreOJ Round #10」mathematican 的二进制(期望 + 分治NTT)
题面 戳这里,题意简单易懂. 题解 首先我们发现,操作是可以不考虑顺序的,因为每次操作会加一个 \(1\) ,每次进位会减少一个 \(1\) ,我们就可以考虑最后 \(1\) 的个数(也就是最后的和) ...
- LOJ2541 PKUWC2018猎人杀(概率期望+容斥原理+生成函数+分治NTT)
考虑容斥,枚举一个子集S在1号猎人之后死.显然这个概率是w1/(Σwi+w1) (i∈S).于是我们统计出各种子集和的系数即可,造出一堆形如(-xwi+1)的生成函数,分治NTT卷起来就可以了. #i ...
- 【BZOJ-3456】城市规划 CDQ分治 + NTT
题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=3456 Solution 这个问题可以考虑dp,利用补集思想 N个点的简单图总数量为$2^{ ...
- CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】
题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...
随机推荐
- 【Luogu】P2015二叉苹果树(DP,DFS)
题目链接 设f[i][j][k]表示给以i为根节点的子树分配j条可保留的树枝名额的时候,状态为k时能保留的最多苹果. k有三种情况. k=1:我只考虑子树的左叉,不考虑子树的右叉,此时子树能保留的最多 ...
- BZOJ 2154 Crash的数字表格 ——莫比乌斯反演
求$\sum_{i=1}^n\sum_{j=1}^n lcm(i,j)$ 枚举因数 $ans=\sum_{d<=n} F(d) * d$ $F(d)$表示给定范围内两两$\sum_{gcd(i, ...
- BZOJ 1009 [HNOI2008]GT考试 ——矩阵乘法 KMP
先用KMP处理所有的转移,或者直接暴力也可以. 然后矩阵快速幂即可. #include <cstdio> #include <cstring> #include <ios ...
- 二分图最小覆盖的Konig定理及其证明,最小的覆盖证明
[转http://www.cppblog.com/abilitytao/archive/2009/09/02/95147.html -> http://yejingx.ycool.com/p ...
- 圆桌聚餐(cogs 729)
«问题描述:假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为ri(i=1,2,3...m), .会议餐厅共有n张餐桌,每张餐桌可容纳c i(i=1,2...n) 个代表就餐.为了 ...
- CodeForces 762D Maximum path
http://codeforces.com/problemset/problem/762/D 因为是3*n很巧妙的地方是 往左走两步或更多的走法都可以用往回走以一步 并走完一列来替换 那么走的方法就大 ...
- Redis集群模式配置
redis集群部署安装: https://blog.csdn.net/huwh_/article/details/79242625 https://www.cnblogs.com/mafly/p/re ...
- Spring Boot 2 快速教程:WebFlux 集成 Mongodb(四)
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第104篇原创 文章工程:* JDK 1.8* M ...
- Java I/O概述
Java的I/O通过java.io包下的类.接口来支持.在java.io包下主要包括输入.输出两种IO流,每种输入.输出流又可分为字符流.字节流两大类. 字符流以字符为单位处理输入.输出操作,字节流以 ...
- iOS Block学习
iOS4已经直接支持blocks,很有必要学习一下. 在ios中,将blocks当成对象来处理,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数的返回值,而其 本身又 ...