UVA 369题Combinations(一个排列组合问题)
2012-05-26 17:14
567 查看
从n个球中拿m个球有多少种方法?就是数学上的c(n,m)。你能用程序写出来么?比如要求c(100,6),数据那么大,你如何处理?
Combinations
DescriptionComputing the exact number of ways that N things can be takenM at a time can be a great challenge whenN and/or
M become very large. Challenges are the stuff of contests. Therefore, you are to make just such a computation given the following:
GIVEN:
Compute the EXACT value of:
You may assume that the final value of C will fit in a 32-bit Pascal LongInt or a C long.
For the record, the exact value of 100! is:
93,326,215,443,944,152,681,699,238,856,266,700,490,715,968,264,381,621, 468,592,963,895,217,599,993,229,915,608,941,463,976,156,518,286,253, 697,920,827,223,758,251,185,210,916,864,000,000,000,000,000,000,000,000
The input to this program will be one or more lines each containing zero or more leading spaces, a value forN, one or more spaces, and a value forM. The last line of the input file will contain a dummyN,
M pair with both values equal to zero. Your program should terminate when this line is read.
The output from this program should be in the form:
N things taken M at a time isCexactly.
输入
100 6
20 5
18 6
0 0
输出
100 things taken 6 at a time is 1192052400 exactly.
20 things taken 5 at a time is 15504 exactly.
18 things taken 6 at a time is 18564 exactly.
题意:一个数学上的排列组合问题,题目的意思也很明了,输入n和m,假设是n个球,编号为1.2.3.。。。。。。。n,从其中拿出m个球,求解有多少种拿法,即求c(n,m)。至于式子在上面也有。但问题也很明显,根据我们做数学题时的方法,算出各自的阶乘,数据太大,用int,long等都无法算出。为此我一直纠结着。然后我想到了递归,是的,递归很简单,代码很短,即根据c(n,m)=c(n,m-1)+c(n-1,m-1),而且当m==n和m==0时都有c(n,m)=1,运行结果也对了,我乐呵呵的去提交,却总是超时。。。也是,这个数据用这个算法,不超时才怪,我看到一些已经ac的都只花了一点点时间,我起初想着去优化这个递归,但做了无用功。。。这个题是我在比赛的最后半个小时,转换方法写出来的。哎,之前脑袋短路,没办法。嗯,我想到,既然最后结果是在long的范围内的,那么我在计算答案时,在计算分子时,每要乘以一个数,我都在分母里面找它的最大公约数,直到分母里已经没有能整除这个数了(除了1)。这样算下来,终于,用了乘法也没超出范围,时间是20ms。。。
#include<iostream> #include<cmath> using namespace std; int gcd(int a,int b) //计算最大公约数 { return (!b)?a:gcd(b,a%b); } int main() { int m,n,a[100],top,low; //这里top和low是用来记录分子分母各自阶乘的终点和起点,即这里c(n,m)=(low*(low+1)*(low+2)....*n)/top! long c; while(cin>>n>>m && (n||m)) { int i,j,k,x; c=1; if(m>n-m+1) //我们知道,c(n,m)=c(n,n-m),这里使得分子和分母没有同样的因子 { low=m+1; top=n-m; } else { low=n-m+1; top=m; } //主要就是这里,每次要乘以一个分子,都在每个分母里找公约数,然后约去,化简.具体思想参见代码 for(i=1;i<=top;i++) a[i]=i; for(i=low;i<=n;i++) { k=i; for(j=2;j<=top;j++) { x=gcd(k,a[j]); while(a[j]!=1 && x!=1) { k/=x; a[j]/=x; x=gcd(k,a[j]); } } c*=k; } cout<<n<<" things taken "<<m<<" at a time is "<<c<<" exactly."<<endl; } return 0; }
相关文章推荐
- 一个排列组合的分组问题
- 求一个数组,n个元素的不同组合(排列组合问题)
- uva 1380 - A Scheduling Problem 一个调度问题 好难的动态规划
- UVa 369 Combinations (用double算组合数)
- uva 784 DFS 染色问题。有坑点。一个getchar()
- UVa 369 - Combinations
- 一个排列组合的问题
- UVa 369 - Combinations
- 【uva1380 - 一个调度问题】思路题+树形dp
- UVa:369 Combinations
- POJ1306 UVA369 UVALive5341 Combinations【组合计算】
- UVa369 - Combinations
- fopen_s遇到的一个问题
- ExpandableStickyListHeadersListView遇到的一个问题
- 【Maven+SSM】如何通过Mybatis写一个中文查询请求及所遇到的问题
- 高分求教一个怪异的问题
- 一个调用问题
- 一个跟正则有关的字符串匹配问题
- iOS学习笔记-workspace添加工程时只有一个proj文件问题
- uva 10385 一个单峰函数(由min(很多一次函数)构成)和一个一次函数的差值 也是单峰函数