码迷,mamicode.com
首页 > 其他好文 > 详细

nyoj743-复杂度 【排列组合】

时间:2015-02-28 22:50:17      阅读:258      评论:0      收藏:0      [点我收藏+]

标签:

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\n",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

 

nyoj743-复杂度 【排列组合】

标签:

原文地址:http://www.cnblogs.com/jiu0821/p/4306243.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!