LUOGU P2822 组合数问题

题面

解题思路

由于要求对k取模为0的值,所以我们递推求组合数时一直对k取模就行了
然后算出二维前缀和,O(n^2)预处理,O(1)回答。BZOJ上和这个不太一样,
那个是要卢卡斯定理。

代码

#include<bits/stdc++.h>
#define LL long long

using namespace std;
const int MAXN = 2005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int n,m,t,k;
LL ans[MAXN][MAXN];
LL C[MAXN][MAXN];

int main(){
    t=rd();k=rd();
    C[1][0]=1;C[1][1]=1;C[0][0]=1;
    for(register int i=2;i<=MAXN;i++){  
        C[i][0]=1;
        for(register int j=1;j<=i;j++){
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%k;
            ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];
            if(C[i][j]==0) ans[i][j]++;
//          cout<<i<<" "<<j<<" "<<ans[i][j]<<endl;
        }
        ans[i][i+1]=ans[i][i];  //注意此处,因为ans[i][j]要被
    }                          //ans[i-1][j]更新,当i=j时i比j小
    for(register int i=1;i<=t;i++){
        n=rd();m=rd();
        if(m>n) m=n;
        printf("%lld
",ans[n][m]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9677013.html