zoukankan      html  css  js  c++  java
  • 题解 【NOIP2016】组合数问题

    【NOIP2016】组合数问题

    Description

    Pic

    Input

    第一行有两个整数t, k,其中t代表该测试点总共有多少组测试数据,k的意义见【问题描述】。
    接下来t行每行两个整数n, m,其中n, m的意义见【问题描述】。

    Output

    t行,每行一个整数代表所有的0<=i<=n,0<=j<=min(i,m)中有多少对(i, j)满足C(j,i)是k的倍数。

    Sample Input

    输入1:
    1 2
    3 3

    输入2:
    2 5
    4 5
    6 7

    Sample Output

    输出1:
    1

    输出2:
    0
    7

    Hint

    样例1提示:
    在所有可能的情况中,只有C(1,2)是2的倍数。

    输出范围:
    Pic

    Source

    NOIP2016 ,数学, 杨辉三角

    解析

    这题看上去确实很难做哈。

    毕竟这数据范围。。

    但实际上,我们完全可以利用杨辉三角预处理出组合数模k的值,

    这样只要模k为0就是k的倍数了。

    然后再O(2000*2000)记录下次数就能O(1)回答了。

    上AC代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    int t,k,m,n;
    int f[2002][2002],a[2002][2002];
    
    int main(){
        scanf("%d%d",&t,&k);
        for(int i=0;i<=2000;i++){
            f[i][0]=1%k;
        }
        for(int i=1;i<=2000;i++){
            for(int j=1;j<=i;j++){
                f[i][j]=(ll)(f[i-1][j]+f[i-1][j-1])%k;
            }
        }/*计算杨辉三角模k的值*/
        if(!f[0][0]) a[0][0]=1;
        for(int i=1;i<=2000;i++){
            a[i][0]=a[i-1][0]+(f[i][0]==0);
            for(int j=0;j<i;j++){
                a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+(f[i][j]==0);
                //如果值为0就是k的倍数
            }
            a[i][i]=a[i][i-1]+(f[i][i]==0);
            for(int j=i+1;j<=2000;j++) a[i][j]=a[i][i];
        }/*预处理计数*/
        for(int i=1;i<=t;i++){
            scanf("%d%d",&n,&m);
            printf("%d
    ",a[n][m]);
            //O(1)回答
        }
        return 0;
    }
  • 相关阅读:
    程序编译与代码优化 -- 早期(编译期)优化
    Java字节码指令
    知识点
    Openresty配置文件上传下载
    Openresty + nginx-upload-module支持文件上传
    G1日志分析
    Garbage First(G1)垃圾收集器
    Java内存分析工具jmap
    编译JDK1.7
    Java服务CPU占用高问题定位方法
  • 原文地址:https://www.cnblogs.com/zsq259/p/10458722.html
Copyright © 2011-2022 走看看