zoukankan      html  css  js  c++  java
  • [noip2016]组合数问题<dp+杨辉三角>

    题目链接:https://vijos.org/p/2006

    当时在考场上只想到了暴力的做法,现在自己看了以后还是没思路,最后看大佬说的杨辉三角才懂这题。。。

    我自己总结了一下,我不能反应出杨辉三角的递推是因为对组合C和排列S不熟悉导致的,这些公式基本都是我的短板

    从杨辉三角形看出,杨辉三角的i,j位(有0位)就是在i个数选j个出来的方案数,,我们来看下杨辉三角吧

    ------------------------------------------------------------------------------------------------------------------------------

    1

    1  1

    1  2  1

    1  3  3  1

    1  4  6  4  1

    1  5  10  10   5  1

    1  6  15  20   15   6  1

    ………………………………………………

    --------------------------------------------------------------------------------------------------------------------------------

    只需要赋初值最上面那个a[0][0]为1就可以预处理出这个2000*2000的图了。。。。

    输入n,m只需要判断0<=i<=n和0<=j<=min(n,m)的所有数是不是k的倍数,这个来源就是n,m的左方和上方的数,用以n,m为原点的坐标系说就是第二象限的值,包括x负半轴y正半轴

    所以维护一个line[j]表示到当前为止,第j列有几个是k的倍数,然后就是自己这列的个数加上num[i-1][j]

    num[i][j]=num[i-1][j]+line[j]

    然后就可以愉快的做这道题了,最后提醒一点

    所有的杨辉三角的值对k取个模,因为我们只是找k个倍数

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<cmath>
     6 #include<iostream>
     7 #include<cstdlib>
     8 #define maxn 2005
     9 using namespace std;
    10 
    11 int t,k,a[maxn][maxn];
    12 int num[maxn][maxn];
    13 int n,m,line[maxn];
    14 
    15 void show(int x){
    16     for(int i=0;i<=x;i++){
    17         for(int j=0;j<=i;j++){
    18             printf("%d ",a[i][j]); 
    19         }
    20         printf("
    ");
    21     }
    22 }
    23 
    24 void show2(int x){
    25     for(int i=0;i<=x;i++){
    26         for(int j=0;j<=i;j++){
    27             printf("%d ",num[i][j]); 
    28         }
    29         printf("
    ");
    30     }
    31 }
    32 
    33 int main(){
    34     for(int i=0;i<=2000;i++)
    35         a[i][0]=1;
    36     scanf("%d%d",&t,&k);
    37     for(int i=1;i<=2000;i++){
    38         for(int j=1;j<=i;j++){
    39             a[i][j]=(a[i-1][j-1]+a[i-1][j])%k;
    40             int look=a[i][j];
    41             if(a[i][j]==0){//是k倍数 
    42                 line[j]++;
    43             }
    44             num[i][j]=num[i][j-1]+line[j];
    45         }
    46     }
    47 //    show(6);
    48 //    show2(6);    
    49     for(int i=1;i<=t;i++){
    50          scanf("%d%d",&n,&m);
    51          m=min(m,n);
    52          printf("%d
    ",num[n][m]);
    53     }
    54 //show函数只是用来输出这个表,看下有没有误而已,可以删去    
    55 }
    View Code

    总结:很多一看就知道爆数组爆longlong的题,把结果用表格对应写出来,说不定会有意想不到的惊喜

  • 相关阅读:
    Python 魔法方法
    使用PHP7来批量更新MangoDB数据
    git 小乌龟安装教程
    webpack初学者(1)
    移动端与PC端的触屏事件
    解决onclick事件的300ms延时问题
    尺寸单位em,rem,vh,vw
    ngRoute 与ui.router区别
    angular.js的依赖注入解析
    ionic的基础学习(第一篇)
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7674177.html
Copyright © 2011-2022 走看看