• 题解 【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;
    }
  • 相关阅读:
    10个对Web开发者最有用的Python包
    9款最好的JavaScript压缩工具
    推荐15款制作 SVG 动画的 JavaScript 库
    2016年最好的15个Web设计和开发工具
    整理六百篇web前端知识混总
    9款免费的跨浏览器测试工具
    9个有用的和免费的工具来支持动态网页开发
    8个基本的引导工具的网页设计师
    11款CSS3动画工具的开发
    2016年某前端群题目答案参考
  • 原文地址:https://www.cnblogs.com/zsq259/p/10458722.html
Copyright © 2020-2023  润新知