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\n",ans[n][m]);
    }
    return 0;
}            

                
            
        
浙公网安备 33010602011771号