首页 > 代码库 > 组合数问题

组合数问题

组合数问题

Description

技术分享

技术分享

科普:组合数公式:C(n,m)=C(n,m-1)+C(n-1,m-1)

对于一对n,m 可以用杨辉三角递推出C(n,m)

 

 

 

而这道题中由于 t<=104 不能直接进行求解

所以我们可以离线处理,具体操作如下:

1.对于每一次询问中的 i , j 分别取出对应的最大值 imax , jmax

2.利用组合数公式进行递推打表,维护一个数组s[i][j],如果C(i,j)是k的倍数,记s[i][j]=1;

3.利用二维前缀和 令s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]

 

 

 

最后对于每次询问可在O(1)时间内求出答案

 

 

#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
int t,k;
int c[2005][2005],sum[2005][2005],N[10005],M[10005],Nmax,Mmax,P;
int main()
{
    scanf("%d%d",&t,&k);;
    for(int i=1;i<=t;i++)
    {
        scanf("%d%d",&N[i],&M[i]);
        Nmax=max(Nmax,N[i]);
        Mmax=max(Mmax,M[i]);
    }
    c[0][0]=1;
    for(int i=1;i<=Nmax;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=i;j++)
        {
            c[i][j]=(c[i-1][j]%k+c[i-1][j-1]%k)%k;
            if(c[i][j]==0) sum[i][j]=1;
        }
    }
    for(int i=0;i<=Nmax;i++)
        for(int j=0;j<=Mmax;j++)
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    for(int i=1;i<=t;i++)
    {
        printf("%d\n",sum[N[i]][M[i]]);
    }
}

 

 

组合数问题