HDU 4373 Mysterious For(Lucas 定理 + 中国剩余定理)
2015-09-16 01:14
351 查看
HDU 4373(Lucas 定理 + 中国剩余定理)
题意:
一段程序共有m个for循环嵌套,有两种形式,第一类从1开始到n,第二类初始值为上一层当前值,累计到n,第一层一定是第一种类型,求总的循环的次数对364875103取余的结果。思路:
fuck the 364875103!!!TMD居然是个合数!一开始觉得顺序对结果没啥影响,yy出答案为nk−1∗Cm−k+1m+n−kn^{k-1}*C_{m+n-k}^{m-k+1},并且很不幸地样例都过了,于是怒吃一发WA。
后来发现还是有一定影响的,每一个第一类循环都会截断当前状态,所以我们把m层循环分为k个部分,每个部分的起始都是第一类循环,每个部分长度为 lenlen ,循环次数等于 Clenn+len−1C_{n+len-1}^{len},最后把这k个次数乘起来即可。
由于mod是个合数,所以求组合数取余要用到lucas+CRT。
代码:
[code]/* * @author FreeWifi_novicer * language : C++/C */ #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<map> #include<set> #include<vector> #include<queue> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define pr( x ) cout << #x << " = " << x << endl #define pri( x ) cout << #x << " = " << x << " " #define mp make_pair #define pb push_back typedef long long lint; const lint p1 = 97 ; const lint p2 = 3761599 ; const lint MOD = p1 * p2 ; lint fac1[p1+5] , fac2[p2+5] ; int pos[18] ; lint inv1 , inv2 ; lint fast_pow( lint x , lint n , lint p ){ x %= p ; lint res = 1 ; while( n ){ if( n & 1 ) res = res * x % p ; n >>= 1 ; x = x * x % p ; } return res ; } void init(){ fac1[0] = fac2[0] = 1 ; for( int i = 1 ; i <= p1 ; i++ ) fac1[i] = fac1[i-1] * i % p1 ; for( int i = 1 ; i <= p2 ; i++ ) fac2[i] = fac2[i-1] * i % p2 ; inv1 = p2 * fast_pow( p2 , p1 - 2 , p1 ) ; inv2 = p1 * fast_pow( p1 , p2 - 2 , p2 ) ; } lint C( lint n , lint m , lint p , lint *fac){ if( n < m ) return 0 ; return fac * fast_pow( fac[m] * fac[n-m] , p-2 , p ) % p ; } lint lucas( lint n , lint m , lint p , lint *fac ){ if( m == 0 ) return 1 ; return C( n % p , m % p , p , fac ) * lucas( n / p , m / p , p , fac ) % p ; } int main(){ //freopen("input.txt","r",stdin); int t ; cin >> t ; int kase = 1 ; init() ; while( t-- ){ lint n , m ; int k ; scanf( "%I64d%I64d%d" , &n , &m , &k ) ; for( int i = 0 ; i < k ; i++ ) scanf( "%d" , &pos[i] ) ; pos[k] = m ; lint ans = 1 ; for( int i = 0 ; i < k ; i++ ){ int len = pos[i+1] - pos[i] ; lint tmp1 = lucas( n + len - 1 , len , p1 , fac1 ) ; lint tmp2 = lucas( n + len - 1 , len , p2 , fac2 ) ; lint tmp = ( tmp1 * inv1 + tmp2 * inv2 ) % MOD ; ans = ( ans * tmp ) % MOD ; } printf( "Case #%d: %I64d\n" , kase++ , ans ) ; } return 0; }
相关文章推荐
- Android中Intent对象与Intent Filter过滤匹配过程详解
- 面试中如何“投机取巧”
- Rectangle Area
- IOS征途之三 分类与协议
- maven jetty myeclipse 进行debug
- TCP协议流量控制与拥塞避免【转载】
- Activity 通过 Fragment保存大块数据的一种方法。摘自android开发官网 3ff8
- Win10实现窗口AeroGlass化
- word frequency
- android 状态栏一体化实现
- Adapter&&GroupAdapter&&VerifyAdapter&&PicAdapter
- storm-kafka数据流量问题
- MySQL5.6 部署MHA
- android网络游戏开发——网络通信——IO处理
- 设计模式学习笔记二十六:装饰器模式
- HDU 1695 GCD(莫比乌斯反演)
- Java9: REPL环境与编程
- java
- 【剑指Offer】矩形覆盖
- 在openwrt中对https 数据的转发到 云端