• 组合数问题(组合数学+二维前缀和)


    洛咕

    题意:给定n,m,k,对于所有的(0<=i<=n,0<=j<=min(i,m))有多少对((i,j))满足(C_i^j)是k的倍数?

    分析:有多组数据,肯定考虑预处理,然后(O(1)回答).(n,m<=2000)可以考虑组合数的线性递推式(C[i][j]=C[i-1][j]+C[i-1][j-1]),因为只有k的倍数才会对答案产生贡献,所以可以递推的时候直接对k取模,然后二维前缀和(f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1])统计的时候只要看是否为零就可以了.

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    int t,k,n,m;
    int f[2005][2005],C[2005][2005];
    int main(){
        t=read();k=read();
        for(int i=0;i<=2000;i++)
    		C[i][0]=C[i][i]=1;
    //组合数初始化
        for(int i=1;i<=2000;i++)
    		for(int j=1;j<=i;j++)
    	    	C[i][j]=(C[i-1][j]+C[i-1][j-1])%k;
    //线性递推,直接模k
        for(int i=1;i<=2000;i++)
    		for(int j=1;j<=2000;j++){
    	    	f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
    	    	if(C[i][j]==0&&i>=j)f[i][j]++;
    	}
    //二维前缀和统计答案
        while(t--){
    		n=read();m=read();
    		printf("%d
    ",f[n][m]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    接口测试—-工具篇,实现接口自动化
    接口自动化测试,完整入门篇
    接口测试系列汇总
    Java教程
    补充三:国际化
    补充二:会话控制——Cookie
    补充一:EL简介
    ES6——JavaScript 的下一个版本标准
    hibernate---session查询
    缓存技术--页面缓存
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10587120.html
Copyright © 2020-2023  润新知