[2011山东ACM省赛] Binomial Coeffcients(求组合数)

Binomial Coeffcients

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

 

输入

 

输出

 

示例输入

3
1 1
10 2
954 723

示例输出

1
45
3557658

提示

 

来源

山东省第二届ACM大学生程序设计竞赛

解题思路:

这道题坑死我了。。本来很简单的一道题,却怎么也做不对。。就是求组合数,结果对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;//直接输出
    }
}


 

原文地址:https://www.cnblogs.com/sr1993/p/3697895.html