• 组合数


    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    
    const int MAXN=2000,MAXM=2000;
    
    int t,k,table[MAXM][MAXN],ser[MAXM][MAXN],h[MAXN];
    //table数组用来打杨辉三角表(边打表边取余)
    //取余公式非常简单 (a+b)%c=((a%c)+(b%c))%c;
    //ser数组用来存储C(j,i)范围内的可以整除k的个数
    //k数组用于动态的存储当前行里有多少个满足条件的C(j,i)
    //简单介绍杨辉三角
    //nm 0 1 2  3  4  5 6
    //0   1
    //1   1 1
    //2   1 2 1
    //3   1 3 3  1
    //4   1 4 6  4  1
    //5   1 5 10 10 5  1 
    //6   1 6 15 20 15 6 1
    //上面的横排是C(m,n)中的m
    //竖排是C(m,n)中的n
    //于是我们可以很简单用一个矩阵+dp求出所有的组合数
    //满足公式C(m,n)=C(m,n-1)+C(m-1,n-1)
    //当然接下来我的代码忽略了m=0和n=0的情况 
    int main(){
        cin>>t>>k;
        //预处理开始 
        for(int i=0;i<MAXM;++i){
            for(int j=0;j<i;++j){//复杂度O( n(n-1)m/2 ) n是MAXN,m是操作步数
                if(j==0){//第一竖行都是i+1 我直接单独处理 
                    table[i][j]=(i+1)%k;//杨辉三角的dp求解 
                    if(!table[i][j]){
                        ++h[i];//如果满足整除k 就记录在h中
                    }
                    ser[i][j]=ser[i-1][j]+h[i];//这里dp出C(1,1)到C(i,j)有多少个满足条件的组合数 
                    //cout<<ser[i][j]<<" ";
                    continue;
                }
                table[i][j]=(table[i-1][j]+table[i-1][j-1])%k; //杨辉三角的dp求解 
                if(!table[i][j]){
                    ++h[i];//如果满足整除k 就记录在h中
                }
                ser[i][j]=ser[i-1][j]+h[i];//这里dp出C(1,1)到C(i,j)有多少个满足条件的组合数 
                //cout<<ser[i][j]<<" ";
            }
            //对于C(i,i)也就是j=i的情况单独处理 一定是1 
            table[i][i]=1%k;
            if(i==0&&!table[0][0]){
                ++ser[0][0];
                continue;
            }
            ser[i][i]+=ser[i][i-1];
            if(!table[i][i]){
                ++ser[i][i];
            }
            //cout<<ser[i][i]<<endl;
        }
        for(int i=0;i<t;++i){//查询操作直接O(1)完成 
            int n,m;
            cin>>n>>m;
            --n,--m;
            if(m>n)m=n;//注意m可能大于n 
            cout<<ser[n][m]<<endl; 
        } 
        return 0;
    }
  • 相关阅读:
    python day 6 time 库
    python day 5 基本数据类型
    20191206《信息安全导论》第六周学习总结
    第十节 数据流重定向
    第九节 简单的文本处理
    第八节 命令执行顺序控制与管道
    第七节 文件系统操作与磁盘管理
    第六节 文件打包与解压缩
    第五节 环境变量与文件查找
    第四节 Linux目录文件及文件基本操作
  • 原文地址:https://www.cnblogs.com/voldemorte/p/7234794.html
Copyright © 2020-2023  润新知