程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU4373 Mysterious For

HDU4373 Mysterious For

編輯:C++入門知識

2012 Multi-University Training Contest 8
題意:
m個for循環嵌套,有兩種形式,第一類從1開始到n,第二類從上一層循環當前數開始到n,第一層一定是第一種類型,問總的循環的次數對364875103取余的結果。

首先可以看出,每一個第一類循環都是一個新的開始,與前面的狀態無關,所以可以把m個嵌套分為幾個不同的部分,每一個部分由第一類循環開始,最終結果相乘就可以。
剩下的就是第二類循環的問題,假設一個m層循環,最大到n,
只有第一層:循環n次。
只有前兩層:循環n + (n - 1) + ... + 1 = (n + 1) * n / 2 = C(n + 1, 1)
只有前三層:
      (n + 1) * n / 2 + n * (n - 1) / 2 + ... + 1
    = (1 + 2 + ... + n) / 2 + (1 + 4 + ... + n^2) / 2
    = (n + 1) * n / 2 / 2 + n * (n + 1) * (2n + 1) / 6 / 2
    = (n + 2) * (n + 1) * n / 6 = C(n + 2, 2)
……
找規律得第m層:C(n + m - 1, m)

接下來的問題就是如何求出這些東西對364875103的模,由於n和m都非常大,暴力統計必然是不行的。
364875103 = 97 * 3761599 (比賽時候哪有心情拆數玩,這個太不厚道了)
Lucas(n, m, p) = c(n % p,m % p) * Lucas(n / p, m / p, p);
用Lucas定理分別求出兩個質數的余數,然後利用中國剩余定理求出對364875103的余數。

[cpp] 
#include <cstdio> 
#include <cstring> 
#include <algorithm> 
using namespace std; 
const int MAXK = 20; 
const int MOD1 = 97; 
const int MOD2 = 3761599; 
const int MOD = MOD1 * MOD2; 
 
int n, m, k; 
int a[MAXK]; 
__int64 p1[MOD1], p2[MOD2]; 
__int64 c1, c2; www.2cto.com
 
__int64 pow_mod(__int64 x, __int64 y, __int64 mod) 

    __int64 res = 1; 
    while(y) 
    { 
        if(y & 1) 
        { 
            res = (res * x) % mod; 
        } 
        x = (x * x) % mod; 
        y >>= 1; 
    } 
    return res; 

 
__int64 cm(__int64 n, __int64 m, __int64 mod, __int64 p[]) 

    if(n < m) 
    { 
        return 0; 
    } 
    __int64 res = (p[n] * pow_mod(p[m], mod - 2, mod)) % mod; 
    return (res * pow_mod(p[n - m], mod - 2, mod)) % mod; 

 
__int64 lucas(__int64 n, __int64 m, __int64 mod, __int64 p[]) 

    __int64 res = 1; 
    while(n && m && res) 
    { 
        res = (res * cm(n % mod, m % mod, mod, p)) % mod; 
        n /= mod; 
        m /= mod; 
    } 
    return res; 

 
void init() 

    p1[0] = p2[0] = 1; 
    for(int i=1;i<MOD1;++i) 
    { 
        p1[i] = (p1[i-1] * i) % MOD1; 
    } 
    for(int i=1;i<MOD2;++i) 
    { 
        p2[i] = (p2[i-1] * i) % MOD2; 
    } 
    c1 = MOD2 * pow_mod(MOD2, MOD1 - 2, MOD1); 
    c2 = MOD1 * pow_mod(MOD1, MOD2 - 2, MOD2); 

 
int main() 

    init(); 
    int caseNumber; 
    scanf("%d", &caseNumber); 
    for(int cas=1;cas<=caseNumber;++cas) 
    { 
        scanf("%d%d%d", &n, &m, &k); 
        for(int i=0;i<k;++i) 
        { 
            scanf("%d", &a[i]); 
        } 
        a[k] = m; 
        __int64 ans = 1; 
        for(int i=0;i<k;++i) 
        { 
            __int64 m1 = lucas(a[i+1] - a[i] + n - 1, a[i+1] - a[i], MOD1, p1); 
            __int64 m2 = lucas(a[i+1] - a[i] + n - 1, a[i+1] - a[i], MOD2, p2); 
            __int64 mm = (m1 * c1 + m2 * c2) % MOD; 
            ans = (ans * mm) % MOD; 
        } 
        printf("Case #%d: %I64d\n", cas, ans); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved