poj 2249 Binomial Showdown(组合数 公式优化)

//  组合数学,开始了……

题目地址 : poj 2249 Binomial Showdown


Description

In how many ways can you choose k elements out of n elements, not taking order into account?

Write a program to compute this number.

Input

The input will contain one or more test cases.

Each test case consists of one line containing two integers n (n>=1) and k (0<=k<=n).

Input is terminated by two zeroes for n and k.

Output

For each test case, print one line containing the required number. This number will always fit into an integer, i.e. it will be less than 231.

Warning: Don‘t underestimate the problem. The result will fit into an integer - but if all intermediate results arising during the computation will also fit into an integer depends on your algorithm. The test cases will go to the limit.

Sample Input

4 2
10 5
49 6
0 0

Sample Output

6
252
13983816

Source

Ulm Local 1997

/******************************

组合数公式的优化

普通的组合数公式:C(n,m) = n!/((n-m)!*m!) = (n * n-1 * n-2 * n-3 * n-4 * n-5 * n-6 * …… * n-m) / (m * m-1 * m-2 * m-3 * m-4 * m-5 * …… * 2 * 1)

优化 :将分子和分母 的因子分别存到一个数组中 nn[]  (分子)  mm[] (分母),双重循环遍历, 进行各个因子约分,因为 组合数为一个整数 ,即N % M = 0,

所以mm[] 的元素一定可以全部约分为1,然后只需将 mm[] 中的元素相乘就行了。。

******************************/

#include <iostream>
#include<string.h>
#include <stdio.h>
using namespace std;
const int N = 10000;
int nn[N],mm[N];
int gcd(int a,int b)//  求n,m 的最大公约数
{
    return (b==0)?a:gcd(b,a%b);
}
int main()
{
    int i,j,n,m,t,h,sum,temp;
    while(cin>>n>>m&&(n||m))//  程序结束条件是 n,m 中一个为0就行,用||,我开始用&& WA了好多次,要注意
    {
        t = h = 0;
        sum = 1;
        //cout<<gcd(m,n)<<endl;
        if(m>n-m)
            m = n-m;
        for(i = n-m+1;i<=n;i++)// 分子赋值
            nn[t++] = i;
        for(i = 1;i<=m;i++)//  分母赋值
            mm[h++] = i;
        for(i = 0;i<m;i++)
        {
            for(j = 0;j<m;j++)
            {
                temp = gcd(nn[i],mm[j]);//  约分
                nn[i] = nn[i]/temp;
                mm[j] = mm[j]/temp;
            }
        }
        for(i = 0;i<m;i++)
            sum*=nn[i];
        cout<<sum<<endl;
    }
}

poj 2249 Binomial Showdown(组合数 公式优化),布布扣,bubuko.com

时间: 2024-12-25 02:07:19

poj 2249 Binomial Showdown(组合数 公式优化)的相关文章

Uva 10943 - How do you add ?( 组合数公式 + 递推 )

Uva 10943 - How do you add ?( 组合数公式 + 递推 ) 题意:给定一个数N,分解韡k个数,问有多少种组合.数可以重复 (N<=100) 分析:通过组合数学将题目抽象为 N个相同的小球,放入k个不同的盒子中,且允许盒子为空然后就可以用隔板法------> ANS = C(N+M-1,M-1)隔板法--> BD然后再根据组合数的性质可以进行递推(这题数据范围比较小)----> C(A,B) = C(A-1,B) + C(A-1,B-1);预处理一遍之后即可

POJ 3190 Stall Reservations(贪心+优先队列优化)

Description Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A..B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reserv

组合数公式,理解。

Cnm+Cnm-1=Cn+1m<=> Cnm+Cnm-1C11=Cn+1m 从装有n个白球,1个黑球,共n+1个球的口袋中取出m个球, 1.若直接取,由组合数公式可得,其有Cn+1m种取法 2.也可以分成两类: 2.1 一类是取出的m个球全部为白球,有Cnm种取法 2.2 另一类是,取出1个黑球,m-1个白球,Cn+1m种取法 Ckk+Ck+1k+Ck+2k+Ck+3k+-+Ck+nk=Ck+n+1k+1 利用Cnm+Cnm-1=Cn+1m Ckk+Ck+1k=Ck+1k+1+Ck+1k=Ck

UVA - 11609 Teams (排列组合数公式)

In a galaxy far far awaythere is an ancient game played among the planets. The specialty of the game isthat there is no limitation on the number of players in each team, as long asthere is a captain in the team. (The game is totally strategic, so som

每日一dp(1)——Largest Rectangle in a Histogram(poj 2559)使用单调队列优化

Largest Rectangle in a Histogram 题目大意: 有数个宽为1,长不定的连续方格,求构成的矩形中最大面积 /************************************************************************/ /* 思路1. 当前为n的面积如何与n-1相联系,dp[i][j]=max(dp[i-1][k]) , 0<k<=j 描述:i为方块个数,j为高度 但是此题目的数据对于高度太变态,h,1000000000 ,n,1

poj 2154 Color 欧拉函数优化的ploya计数

枚举位移肯定超时,对于一个位移i,我们需要的是它的循环个数,也就是gcd(i,n),gcd(i,n)个数肯定不会很多,因为等价于n的约数的个数. 所以我们枚举n的约数,对于一个约数k,也就是循环个数为n/k这样的个数有phi[k]种,证明网上有很多.所以答案就是 phi[k]*(pow(n,n/k)) (k是n的所有约数) 由于约数会很大所以不能打表,只能单个算. 再由于最后要除以n,如果做除法就不能直接取模,所以我们在算每一次pow(n,n/k)的时候,都少乘一个n,这样就相当于除法了. #i

Poj 1151 Invitation Cards dijkstra 堆优化

很裸的最短路,不过节点数和边数都是1e6,直接dij肯定是不行了,稀疏图用heap优化一下就好 o(╯□╰)o注意STL里面的优先队列是优先级大的(值大的)在前面的,一开始没注意WA了好几发,哎,太粗心了 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #inc

POJ 2249 暴力求组合数

Binomial Showdown Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22692   Accepted: 6925 Description In how many ways can you choose k elements out of n elements, not taking order into account? Write a program to compute this number. Inp

ZOJ 1938 Binomial &amp;&amp;poj 2249 (Binomial Showdown )(睡前一水)

链接:click here 题意: In how many ways can you choose k elements out of n elements, not taking order into account?  Write a program to compute this number. 给你整数n和k,让你求组合数c(n,k). 代码: #include <cstdio> #include <cstring> #include <math.h> type