【ZOJ】3874 Permutation Graph 【FFT+CDQ分治】
来源:互联网 发布:运营商 云计算 编辑:程序博客网 时间:2024/05/30 02:23
传送门:【ZOJ】3874 Permutation Graph
题目分析:
容易知道一个个连通块内部的标号都是连续的,否则一定会有另一个连通块向这个连通块建边,或者这个连通块向另一个连通块建边。而且从左到右左边的连通块内最大的标号小于右边连通块内最小的标号。
然后我们可以构造dp方程:
容易发现右边存在一个卷积,由于给的素数正好是费马素数,所以可以用
my code:
#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )#define cpy( a , x ) memcpy ( a , x , sizeof a )const int P = 786433 ;const int MAXN = 262144 ;const int g = 10 ;LL power ( int a , int b , LL res = 1 ) { for ( LL tmp = a ; b ; b >>= 1 , tmp = tmp * tmp % P ) if ( b & 1 ) res = res * tmp % P ; return res ;}void NTT ( LL y[] , int n , int rev ) { LL inv = power ( n , P - 2 ) , wn , w , t ; for ( int i = 1 , j , k , t ; i < n ; ++ i ) { for ( j = 0 , k = n >> 1 , t = i ; k ; k >>= 1 , t >>= 1 ) j = j << 1 | t & 1 ; if ( i < j ) swap ( y[i] , y[j] ) ; } for ( int s = 2 , ds = 1 , k , i ; s <= n ; ds = s , s <<= 1 ) { wn = power ( g , ( P - 1 ) / s ) ; if ( rev == -1 ) wn = power ( wn , P - 2 ) ; for ( k = 0 ; k < n ; k += s ) { for ( i = k , w = 1 ; i < k + ds ; ++ i , w = w * wn % P ) { y[i + ds] = ( y[i] - ( t = w * y[i + ds] % P ) + P ) % P ; y[i] = ( y[i] + t ) % P ; } } } if ( rev == -1 ) for ( int i = 0 ; i < n ; ++ i ) y[i] = y[i] * inv % P ;}LL x1[MAXN] , x2[MAXN] ;LL f[MAXN] , dp[MAXN] ;void cdq ( int l , int r ) { if ( l + 1 == r ) return ; int m = ( l + r ) >> 1 , n = 1 ; cdq ( l , m ) ; while ( n < r - l + 1 ) n <<= 1 ; for ( int i = 0 ; i < m - l ; ++ i ) x1[i] = dp[i + l] ; for ( int i = m - l ; i < n ; ++ i ) x1[i] = 0 ; for ( int i = 0 ; i < n ; ++ i ) x2[i] = f[i] ; NTT ( x1 , n , 1 ) ; NTT ( x2 , n , 1 ) ; for ( int i = 0 ; i < n ; ++ i ) x1[i] = x1[i] * x2[i] % P ; NTT ( x1 , n , -1 ) ; for ( int i = m ; i < r ; ++ i ) dp[i] = ( dp[i] - x1[i - l] + P ) % P ; cdq ( m , r ) ;}void preprocess () { f[0] = 1 ; for ( int i = 1 ; i < MAXN ; ++ i ) { f[i] = f[i - 1] * ( LL ) i % P ; dp[i] = f[i] ; } cdq ( 1 , 100001 ) ; //for ( int i = 1 ; i <= 10 ; ++ i ) printf ( "%lld\n" , dp[i] ) ;}void solve () { int x , c , n ; int ans = 1 ; scanf ( "%*d%d" , &n ) ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d" , &x ) ; int minv = 0x3f3f3f3f , maxv = 0 ; for ( int j = 0 ; j < x ; ++ j ) { scanf ( "%d" , &c ) ; minv = min ( c , minv ) ; maxv = max ( c , maxv ) ; } if ( maxv - minv + 1 != x ) ans = 0 ; ans = ans * dp[x] % P ; } printf ( "%d\n" , ans ) ;}int main () { int T ; preprocess () ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) solve () ; return 0 ;}
0 0
- 【ZOJ】3874 Permutation Graph 【FFT+CDQ分治】
- zoj 3874 Permutation Graph (cdq分治+NTT)
- 【ZOJ 3874】Permutation Graph
- zoj 3874 Permutation Graph
- 【NTT】 ZOJ 3874 Permutation Graph
- HDU 5730 (CDQ分治 FFT)
- hdu 5730 Shell Necklace cdq分治+FFT
- BZOJ3456:城市规划(EGF+FFT/CDQ分治+FFT)
- BNUOJ 51279[组队活动 Large](cdq分治+FFT)
- HDU 5730 Shell Necklace(CDQ分治+FFT)
- [HDU 5730] Shell Necklace (FFT+CDQ分治)
- HDU 5730 多校1 Shell Necklace (CDQ分治+FFT)
- HDU 5730 Shell Necklace(dp+cdq分治+FFT优化)
- [DP] [1D1D优化] [FFT] [CDQ分治] [HDU5730] Shell Necklace
- BZOJ4836(CDQ分治+FFT(NTT会T))
- 【hdu】5354 Bipartite Graph【cdq分治+并查集】
- cdq分治
- cdq分治
- HBase性能优化方法总结
- cursor: pin S产生原理及解决方法
- 超简单的通过年月得到当月天数,从简单的小例子来解析代码的优化
- 聊聊C++语言-软件和编程
- Android取手机号码
- 【ZOJ】3874 Permutation Graph 【FFT+CDQ分治】
- 控制语句
- 复合类型——引用、指针
- Javaweb验证码生成
- [LeetCode]Isomorphic Strings
- 【2】java全排列
- 2010年山东省第一届ACM大学生程序设计竞赛——Greatest Number
- zoj Capture the Flag 比较难的模拟题
- GitHub里的金子