• nyoj743-复杂度 【排列组合】


    http://acm.nyist.net/JudgeOnline/problem.php?pid=743

    复杂度

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:3
     
    描述

    for(i=1;i<=n;i++)

      for(j=i+1;j<=n;j++)

        for(k=j+1;k<=n;k++)

            operation;

    你知道 operation 共执行了多少次吗;

     
    输入
    输入 m 和n 表示m为for循环的层数,n为for中的n。
    (n,m<=2000),输入以n==0和m==0结束
    输出
    输出operation执行的次数(输入结果mod 1009)
    样例输入
    2 3
    1 3
    2 4
    0 0
    
    样例输出
    3
    3
    6





    解题思路:

    首先m层,每层都有一个值 i、j、k….我们发现这m个值是不重复的,而且是递增序列,于是我们可以想到只需要计算总共有多少中m个数的组合的情况即可,即C(n,m)   —– 从n中任选m个数的种类数。每取出m个数,再递增对应安排在原for循环里,即是一种情况。但是问题又来了,n和m的值最大为2000,因此求C(n,m) 的时候long long 也存不下,而且(n%mod)/(m%mod) != (n/m)%mod;

    这就又需要用到另外的一个公式

    C(n,m)= C (n-1,m) + C (n-1,m-1);

    根据递推公式打表完美解决。

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 #define ll long long
     9 #define N 2001
    10 
    11 int dp[N][N];
    12 
    13 void GetAns();
    14 
    15 int main(){
    16     GetAns();
    17     int m,n;
    18     while(scanf("%d %d",&m,&n),m||n){
    19         if(m>n) puts("0");
    20         else    printf("%d
    ",dp[n][m]);
    21     }
    22     return 0;
    23 }
    24 void GetAns(){
    25     int N1=N-1;
    26     for(int i=1;i<=N1;i++) dp[i][0]=1,dp[i][i]=1;
    27     for(int i=1;i<=N1;i++){
    28         for(int j=i-1;j>0;j--){
    29             dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%1009;
    30         }
    31     }
    32 }
    View Code
  • 相关阅读:
    Raphael入门
    EXT使用SASS修改主题样式问题
    Hough Transform Performance article List
    about utf8 ...
    computer vision resource
    Asp.net 中配置 CKEditor和CKFinder
    压缩格式 zip与tar.gz 区别
    一系列按钮的弹出提示框借助jq实现
    SQL Server2005 sa登录出错~
    正则表达式整理
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4306243.html
Copyright © 2020-2023  润新知