hdu1799(用递推公式求组合的个数)

题目意思:

我们知道,在编程中,我们时常需要考虑到时间复杂度,特别是对于循环的部分。例如,

如果代码中出现

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

那么做了n次OP运算,如果代码中出现

fori=1;i<=n; i++)

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

那么做了n*(n-1)/2 次OP 操作。

现在给你已知有m层for循环操作,且每次for中变量的起始值是上一个变量的起始值+1(第一个变量的起始值是1),终止值都是一个输入的n,问最后OP有总共多少计算量。

http://acm.hdu.edu.cn/showproblem.php?pid=1799

题目分析:

注意观察到,可以发现循环的值是;C(n,m)=n!/(m!*(n-m)!),因为n值过大,不可以直接用公式

组合数学的递推公式:C(n,m)=C(n,m-1)+C(n-1,m-1)

AC代码:

/**

*全排列问题,C(n,m)=n!/(m!*(n-m)!)

*但是考虑到n的值过大,不能用这个方法

*可以用组合公式C(n,m)=C(n-1,m)+C(n-1,m-1)

*C(n,1)=n; C(n,n)=1; C(n,0)=1;

*这样就可以用DP了

*/

#include<iostream>

#include<algorithm>

using namespace std;

int dp[2001][2001];

int main()

{

for(int i=0;i<=2000;i++){

dp[i][1]=i%1007;//C(n,1)=n;

dp[i][0]=dp[i][i]=1;//C(n,0)=C(n,n)=1;

}

for(int i=2;i<=2000;i++){

for(int j=1;j<=i;j++){

dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%1007;

}

}

int t,n,m;

cin>>t;

while(t--){

cin>>m>>n;

cout<<dp[n][m]<<endl;

}

return 0;

}

时间: 2024-10-17 11:58:11

hdu1799(用递推公式求组合的个数)的相关文章

给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数。

题目:给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数. 解题思路: 首先取得数组a的中位数a[aMid],然后在b中二分查找a[aMid],得到b[bMid],b[bSt]到b[bMid]的数小于等于a[aMid],b[bMid+1]到b[bEd]大于等于a[aMid],这样数组a和数组b就被划分为了两个部分,第一个部分的数小于等于a[aMid],第二部分的数大于等于a[aMid],然后统计这两个区域数的个数,个数相加等于k就返回,否则重复二分查找.代码如下: def

C语言求组合

引入 假设5个数 1 2 3 4 5,选3个数求组合.可以按如下思路来考虑 先选取1,从生下的2 3 4 5中选2个求组合,这是一个递归过程 先选取2,从 3 4 5中选2个求组合,仍旧是一个递归过程 选取3,从 4 5中选2个求组合 遇到4,剩下的数字只有1个,不能再选取2个,因此不用继续考虑 定义递归_comb(array, visit, int l, int k) 其中visit是一次递归过程中选取的标记,l是子数列的开始下标,k是需要选取的个数 代码 #include <iostream

欧拉计划013(ProjectEuler013):求出10个数乘积最大的

申明:之前的所有欧拉计划都是用python来写的,的确python来写,代码量极少,学习起来也很方便.但是最近为了找java工作,所以用Java来完成欧拉计划的题,来复习一下Java. Large sum Problem 13 Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. 371072875339021027987979982208375902465101357402

组合的个数

Description 从m个不同元素中取出n (n ≤ m)个元素的所有组合的个数,叫做从m个不同元素中取出n个元素的组合数.组合数的计算公式如下: C(m, n) = m!/((m - n)!n!) 现在请问,如果将组合数C(m, n)写成二进制数,请问转这个二进制数末尾有多少个零. Input 第一行是测试样例的个数T,接下来是T个测试样例,每个测试样例占一行,有两个数,依次是m和n,其中n ≤ m≤ 1000. Output 分别输出每一个组合数转换成二进制数后末尾零的数量. Sampl

hdu2852--KiKi&#39;s K-Number(线段树,求第k个数)

KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2546    Accepted Submission(s): 1174 Problem Description For the k-th number, we all should be very familiar with it. Of course,t

一串数字中有两个只出现一次的数字其余都是成对相同,求这两个数

当然如果这个问题是只有一个不同的数,其他数字成对相同,那么就是把所有数字异或就得出这个数了 这次是有两个只出现一次的数字,其他数字都成对相同 1)先把所有数都异或得到数t 2)算出t的二进制第一个1的位置flag 3)将所有数根据二进制flag位置是否为1分成两组b1[],b2[] (此时每组数字的个数一定是奇数) 4)将b1组异或得到ans1,将b2组异或得到ans2 #include<iostream> #include<stdio.h> using namespace std

编程题:指针变量,实参与形参的引用。已知一个一维数组,求其中前n个数的和。n由键盘输入。

#include<stdio.h> int sum(int *q,int n) { int i,s=0; for(i=0;i<n;i++,q++) s+=*q; return s; } void main() { int num,a[10]={1,2,3,4,5,6,7,8,9,10}; int *p=a; scanf("%d",&num); printf("%d\n",sum(p,num)); } 编程题:指针变量,实参与形参的引用.已知

编程题:已知一个一维数组,求其中前n个数的和。n由键盘输入

#include<stdio.h> int sum(int array[],int n) { int i,s=0; for(i=0;i<n;i++) s+=array[i]; return s; } void main() { int num,a[10]={1,2,3,4,5,6,7,8,9,10}; scanf("%d",&num); printf("%d\n",sum(a,num)); } 编程题:已知一个一维数组,求其中前n个数的和.

求重叠区间个数,某书某题错例分析

大意就是我淘钱买了一本题集,觉得书中有些地方作者太随意,例子错得不严谨,一度阻碍阅读.作为消费者不得不拿出来说一说.本文本着不迷信,实事求是精神.本文编排如下:1.引用书中原例2.主观分析例子有错3.代码运行验证其错4.修正例子代码5.另一个求值代码现在开始. 下面是书中原例引用: 求重叠区间个数 给定多个可能重叠的区间,找出重叠区间的个数.区间定义如下: class Interval { int start; // 起点 int end; // 止点 Interval(int a, intb)