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\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 }