【FZU】2208 cleaning again【模数质因数以3为众数的三进制NTT】
来源:互联网 发布:下载商城软件 编辑:程序博客网 时间:2024/06/05 00:48
传送门:【FZU】2208 cleaning again
简要题意:
在长度为
题目分析:
首先我们知道如果将所有间隔为D的人建边,我们可以得到
考虑子问题:在一个长度为
考虑破环成链,枚举第一个点是否选。
1.第一个点不选
此时考虑将
2.第一个点选
此时我们反过来,使得隔板右边强制有一个点,由于已经选了一个点,且此时第一个点和第二个点不能使用,所以方案数为
由于每个环都是一样的,我们不妨构造多项式:
则总的方案数即多项式
由于所有多项式的阶的和不超过
但是问题还没有结束,因为这个素数并不是我们常用的费马素数,他的质因子
三进制
FFT 具体变换如下:
由Ak=A[0](w3kn)+wkn⋅A[1](w3kn)+w2kn⋅A[2](w3kn)
得yk=y[0]k+wkn⋅y[1]k+w2kn⋅y[2]k
由Ak+(n/3)=A[0](w3k+nn)+wk+(n/3)n⋅A[1](w3k+nn)+w2(k+(n/3))n⋅A[2](w3k+nn)
得yk+(n/3)=y[0]k+wk+(n/3)n⋅y[1]k+w2(k+(n/3))n⋅y[2]k
由Ak+(2n/3)=A[0](w3k+2nn)+wk+(2n/3)n⋅A[1](w3k+2nn)+w2(k+(2n/3))n⋅A[2](w3k+2nn)
得yk+(2n/3)=y[0]k+wk+(2n/3)n⋅y[1]k+w2(k+(2n/3))n⋅y[2]k 蝶形变换和二进制
FFT 一样。
#include <stdio.h>#include <string.h>#include <vector>#include <algorithm>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 200005 ;const int mod = 258280327 ;const int g = 5 ;int x1[MAXN] ;int f[MAXN] , vf[MAXN] ;int gcd ( int a , int b ) { return b ? gcd ( b , a % b ) : a ;}int pow_mod ( int x , int n ) { int res = 1 ; while ( n ) { if ( n & 1 ) res = 1LL * res * x % mod ; x = 1LL * x * x % mod ; n >>= 1 ; } return res ;}void DFT ( int y[] , int n , int rev ) { for ( int i = 1 , j , k , t ; i < n ; ++ i ) { for ( j = 0 , k = n / 3 , t = i ; k ; k /= 3 , t /= 3 ) { j = j * 3 + t % 3 ; } if ( i < j ) swap ( y[i] , y[j] ) ; } for ( int s = 3 , ds = 1 ; s <= n ; ds = s , s *= 3 ) { LL wn = pow_mod ( g , ( mod - 1 ) / s ) ; if ( rev ) wn = pow_mod ( wn , mod - 2 ) ; LL t1 = pow_mod ( wn , s / 3 ) ; LL t2 = t1 * t1 % mod ; for ( int k = 0 ; k < n ; k += s ) { LL w = 1 ; for ( int i = k , j = i + ds ; i < k + ds ; ++ i , ++ j ) { LL X = y[i] ; LL Y = w * y[i + ds] % mod ; LL Z = w * w % mod * y[j + ds] % mod ; y[i] = ( X + Y + Z ) % mod ; y[i + ds] = ( X + t1 * Y + t2 * Z ) % mod ; y[j + ds] = ( X + t1 * t1 % mod * Y + t2 * t2 % mod * Z ) % mod ; w = w * wn % mod ; } } }}void NTT ( int x1[] , int n , int m ) { DFT ( x1 , n , 0 ) ; for ( int i = 0 ; i < n ; ++ i ) { x1[i] = pow_mod ( x1[i] , m ) ; } DFT ( x1 , n , 1 ) ; int nv = pow_mod ( n , mod - 2 ) ; for ( int i = 0 ; i < n ; ++ i ) { x1[i] = 1LL * x1[i] * nv % mod ; }}int c ( int x , int y ) { if ( x < y ) return 0 ; return 1LL * f[x] * vf[y] % mod * vf[x - y] % mod ;}void process ( int n1 , int n ) { x1[0] = 1 ; for ( int i = 1 ; i < n1 ; ++ i ) { x1[i] = ( c ( n - i , i ) + c ( n - i - 1 , i - 1 ) ) % mod ; }}void solve () { int n , k , d ; scanf ( "%d%d%d" , &n , &k , &d ) ; int n1 = 1 ; while ( n1 <= n + 1 ) n1 *= 3 ; int g = gcd ( n , d ) ; process ( n1 , n / g ) ; NTT ( x1 , n1 , g ) ; printf ( "%d\n" , x1[k] ) ;}void preprocess () { f[0] = vf[0] = 1 ; for ( int i = 1 ; i < MAXN ; ++ i ) { f[i] = 1LL * f[i - 1] * i % mod ; vf[i] = pow_mod ( f[i] , mod - 2 ) ; }}int main () { int T ; preprocess () ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { printf ( "Case #%d: " , i ) ; solve () ; } return 0 ;}
- 【FZU】2208 cleaning again【模数质因数以3为众数的三进制NTT】
- FZU 1851 组合数 (分解质因数)
- FZU 1582 众数问题
- FZU 2200 cleaning (环dp的处理)
- 求一个数的质因数
- 数的分解、分解质因数
- 求一个数的质因数
- 求一个数的质因数
- FZU 2200 cleaning dp+预处理
- FZU 2200 cleaning (环形dp)
- 分解质因数, 例如60的质因数为2*2*3*5 = 60
- 质因数个的倒数的数累加
- 求一个数的所有质因数
- 分解任意输入数的质因数
- leetcode_263. Ugly Number 寻找丑数,即质因数只能是2,3,5的数
- UVA 11235 求区间连续数的众数 RMQ
- FZU - 1896 神奇的魔法数
- FZU 1896 — 神奇的魔法数
- python安装MYSQLdb
- Edittext文本选中
- Android中使用RecyclerView和CardView实现瀑布流效果(StaggeredGrid)
- 分享我的大型Java多用户商城系统开发的心得和困难
- URL和URI的区别
- 【FZU】2208 cleaning again【模数质因数以3为众数的三进制NTT】
- java序列化Serializable
- 【知识】打印list中的数据
- 递归和分治思想1 – 数据结构和算法31
- 组合查询
- ssh学习笔记
- H5移动端页面一些坑总结1
- 递归和分治思想2 – 数据结构和算法32
- 自定义View学习之12/4(仿IOS联系人列表)