您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: