The binomial coefficient C(m,n) is defined as

Given four natural numbers p, q, r, and s, compute the the result of dividing C(p,q) by C(r,s).

这是二次项系数,现在给出p,q,r,s,计算C(p,q)除以C(r,s)的结果

Input
Input consists of a sequence of lines. Each line contains four non-negative integer numbers giving values for p, q, r, and s, respectively, separated by a single space. All the numbers will be smaller than 10,000 with p ≥ q and r ≥ s.

输入:包含多组数据,pqrs均小于10000的非负整数。

Output
For each line of input, print a single line containing a real number with 5 digits of precision in the fraction, giving the number as described above. You may assume the result is not greater than 100,000,000.

输出:每行输出除法的结果保留小数点后5位结果,结果保证不超过一亿。

Sample Input
10 5 14 9

93 45 84 59

145 95 143 92

995 487 996 488

2000 1000 1999 999

9998 4999 9996 4998

Sample Output
0.12587

505606.46055

1.28223

0.48996

2.00000

3.99960

思路:指数级的乘法结果太大,运用一些约分的方法防爆。

方法一:

唯一分解定理以前介绍过,大意就是每个数都可以唯一地分解为一堆质数的幂的乘积,如90 = 2 * 3² * 5.其中2和5是一次幂,3是二次幂。

这样我们回到题目数据,显然很多时候我们把分子分母都分解以后会发现能约掉很多质数的幂,这样的话可以采取这样一种策略:用一个数组记录每个质数的幂指数,如果是分子的话就加,是分母的话就减,免去了反复的无用乘除法。当把分子分母们都处理完以后,约分后的分子分母就是答案的分数形式了,此时再求出结果即可。

先把10000以内的素数都记录下来。

然后对每个数据来说,p、s、r-s是分子,q、p-q、r是分母。

接着把这六个数分别代入修改函数,修改素数幂指数数组的值,对于此数组,以90为例,应为every_count={1,2,1,0,0,0,……}。

详见代码,220ms:

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std; int p, q, r, s, primes_size/*10000以内素数个数*/;
int all_primes[];//10000以内素数的按顺序具体记录
int every_count[];//每个素数幂指数的记录数组
bool is_composite[];//判定是否为合数 void modify_count(int a, int d)
{
for (int i = ; a > && i < primes_size; i++)
while (a % all_primes[i] == )
{
every_count[i] += d;//1与-1的传入使得修改写起来简便
a /= all_primes[i];
}
} void add_factorial(int n, int d)
{
for (int i = ; i <= n; i++)//n!
modify_count(i, d);//修改every_count数组
} void get_primes()
{
for (int i = ; i < ; i++)
if (!is_composite[i])
{
for (int j = i*i; j < ; j += i)
is_composite[j] = true;
all_primes[primes_size++] = i;
}
} int main()
{
get_primes();//埃氏筛素数 while (cin >> p >> q >> r >> s)
{
memset(every_count, , sizeof(every_count)); //进行6次分解,1与-1的用途见函数内部
add_factorial(p, );
add_factorial(p-q, -);
add_factorial(q, -); add_factorial(r, -);
add_factorial(r-s, );
add_factorial(s, ); //最后利用素数数组一次性求得答案
double ans = 1.0;
for (int i = ; i < primes_size; i++)
ans *= pow(all_primes[i], every_count[i]); cout << fixed << setprecision() << ans << endl;
} return ;
}

方法二:

也是约分的方式,数学知识降维打击。想必大家都知道上边下边的感叹号是可以约下去一堆的。这里有个知识是,如果你把m!约下去n!,剩下的是n+1~m,数字个数与1~m-n+1相等。也就是可以进行一一对应的double结果乘除。同理约下去(m-n)!也是一样的。

见代码即懂,0ms:

 #include <cstdio>

 int main()
{
int p, q, r, s;
while (~scanf("%d%d%d%d", &p, &q, &r, &s))
{
double ans = 1.0;
for (int i = , j = p-q+, x = , y = r-s+; i <= q || x <= s;)
{
if (i <= q) ans *= (double)(j++)/(i++); if (x <= s) ans *= (double)(x++)/(y++);
}
printf("%.5lf\n", ans);
}
}

最后,虽然方法二严重打击了方法一的信心与自尊心,不过方法一的思想还是很不错的,值得学习。

UVa10375:选择与除法(唯一分解定理)的更多相关文章

  1. Uva 10375 选择与除法 唯一分解定理

    题目链接:https://vjudge.net/contest/156903#problem/E 题意:已知 求:C(p,q)/C(r,s) 其中p,q,r,s都是10^4,硬算是肯定超数据类型的. ...

  2. uva10375 Choose and Divide(唯一分解定理)

    uva10375 Choose and Divide(唯一分解定理) 题意: 已知C(m,n)=m! / (n!*(m-n!)),输入整数p,q,r,s(p>=q,r>=s,p,q,r,s ...

  3. UVA10375 选择与除法 Choose and divide 题解

    题目链接: https://www.luogu.org/problemnew/show/UVA10375 分析: 这道题可以用唯一分解定理来做. 什么是唯一分解定理?百度即可,这里也简介一下. 对于任 ...

  4. Choose and divide(唯一分解定理)

    首先说一下什么是唯一分解定理 唯一分解定理:任何一个大于1的自然数N,如果N不是质数,那么N可以分解成有限个素数的乘积:例:N=(p1^a1)*(p2^a2)*(p3^a3)......其中p1< ...

  5. NOIP2009Hankson 的趣味题[唯一分解定理|暴力]

    题目描述 Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson.现 在,刚刚放学回家的 Hankson 正在思考一个有趣的问题. 今天在课堂上,老师讲 ...

  6. POJ - 1845 G - Sumdiv (唯一分解定理)

    Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S m ...

  7. HDU 6069 Counting Divisors(唯一分解定理+因子数)

    http://acm.hdu.edu.cn/showproblem.php?pid=6069 题意: 思路: 根据唯一分解定理,$n={a_{1}}^{p1}*{a2_{}}^{p2}...*{a_{ ...

  8. Irrelevant Elements UVA - 1635 二项式定理+组合数公式+素数筛+唯一分解定理

    /** 题目:Irrelevant Elements UVA - 1635 链接:https://vjudge.net/problem/UVA-1635 题意:給定n,m;題意抽象成(a+b)^(n- ...

  9. UVA - 10375 Choose and divide[唯一分解定理]

    UVA - 10375 Choose and divide Choose and divide Time Limit: 1000MS   Memory Limit: 65536K Total Subm ...

随机推荐

  1. bfs 邻接表(需要优化 可能会RE *【模板】)

    //---基于邻接表的bfs #include <stdio.h> #include <string.h> #include <iostream> #include ...

  2. 基于BASYS2的VHDL程序——数字钟(最终版)

    转载请注明原地址:http://www.cnblogs.com/connorzx/p/3674178.html 调时电路正常工作.一切正常.发现做FPGA还是得从数电的思路思考,设置一个预置使能端,预 ...

  3. 如何强制ffmpeg编码时输出一个关键帧

    http://blog.csdn.net/ashlingr/article/details/7829429 如何强制ffmpeg编码时输出一个关键帧   如何强制ffmpeg编码时输出一个关键帧 AV ...

  4. BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告

    题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=530 (格式有一点点问题,直接粘 ...

  5. css绘制三角形

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. mysql 数据库修改用户名和密码

    因为经常修改数据库密码,也找到了几种修改数据库密码的方式,在这里给大家介绍下供大家参考通过navicat 管理数据库客户端来修改数据库密码: 选择数据库 --- 点击导航条的用户  --- 编辑用户 ...

  7. <编译>条件编译——判断当前使用的编译器及操作系统

    有时候编译需要多平台运行的代码,需要一些条件编译,经常忘记,这里专门记录一下,方便下次查找.   编译器 GCC #ifdef __GNUC__ #if __GNUC__ >= 3 // GCC ...

  8. pytest用例setup和teardown

    函数式以下两种: setup_function/teardown_function  每个用例开始和结束调用一次 setup_module/teardown_module     setup_modu ...

  9. C - Bear and Five Cards

    Description A little bear Limak plays a game. He has five cards. There is one number written on each ...

  10. Qt .pro文件配置大全!

    避免以后的无意义重复劳动,将用过的所有的头文件库文件的配置都放在这里,以后要用的话直接copy就好. eigen3: INCLUDEPATH += \ /usr/local/include/eigen ...