1. 程式人生 > >組合數問題

組合數問題

一個數 bsp 最大 des blog scan using std clu

組合數問題

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]]); } }

組合數問題