1. 程式人生 > >[2011山東ACM省賽] Binomial Coeffcients(求組合數)

[2011山東ACM省賽] Binomial Coeffcients(求組合數)

取余 cor memory -s sin mage pad ruby end

Binomial Coeffcients

Time Limit: 1000ms Memory limit: 65536K 有疑問?點這裏^_^

題目描寫敘述

技術分享

輸入

技術分享

輸出

技術分享

演示樣例輸入

3
1 1
10 2
954 723

演示樣例輸出

1
45
3557658

提示

來源

山東省第二屆ACM大學生程序設計競賽

解題思路:

這道題坑死我了。。

本來非常easy的一道題,卻怎麽也做不正確。。就是求組合數。結果對10000003取模。一開始對c(m,n)是用公式直接求的。可是計算過程中涉及到取余。不能用下面代碼寫:

int c(int m,int n)
{
    int sum=1;
    for(int i=1;i<=n;i++)
    {
        sum=sum*(m--)/i;
        sum%=mod;
    }
    return sum;
}


這個代碼是錯誤的。

比方 C(9,3)對5取余 上面的代碼 的計算過程是這種 sum=sum*9/1 sum=9 sum%5=4 4*8/2=16 16%5=1 1*7/3 =?這下問題出來了把。不能整除。這個計算過程中不能進行取模運算,可是直接算又越界。後來又想到求組合數分子分母進行約分以後再計算,測試數據對。可是可憐的超時。哎。。因此僅僅能用組合遞推得來算,由於每遞推到一個數,假設它大於mod,就取模。這種一個組合式是正確的。由於題意就這樣說得。因此由遞推得到的每個組合式都是正確的。並且不會越界。

另外須要註意的是: c[0][0]=1 這個題少了這一句就WA

代碼:

#include <iostream>
#include <string.h>
using namespace std;
const int mod=10000003;
const int N=1002;
int c[N][N];

void init()//遞推打表
{
    memset(c,0,sizeof(c));
    c[0][0]=c[1][0]=c[1][1]=1;
    for(int i=2;i<N;i++)
    {
        c[i][i]=c[i][0]=1;
        for(int j=0;j<i;j++)
        {
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;//不會越界
        }
    }
}
int main()
{
    init();
    int k;cin>>k;
    int a,b;
    while(k--)
    {
        cin>>a>>b;
        cout<<c[a][b]<<endl;//直接輸出
    }
}


[2011山東ACM省賽] Binomial Coeffcients(求組合數)