UVa10375:选择与除法(唯一分解定理)
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:选择与除法(唯一分解定理)的更多相关文章
- Uva 10375 选择与除法 唯一分解定理
题目链接:https://vjudge.net/contest/156903#problem/E 题意:已知 求:C(p,q)/C(r,s) 其中p,q,r,s都是10^4,硬算是肯定超数据类型的. ...
- 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 ...
- UVA10375 选择与除法 Choose and divide 题解
题目链接: https://www.luogu.org/problemnew/show/UVA10375 分析: 这道题可以用唯一分解定理来做. 什么是唯一分解定理?百度即可,这里也简介一下. 对于任 ...
- Choose and divide(唯一分解定理)
首先说一下什么是唯一分解定理 唯一分解定理:任何一个大于1的自然数N,如果N不是质数,那么N可以分解成有限个素数的乘积:例:N=(p1^a1)*(p2^a2)*(p3^a3)......其中p1< ...
- NOIP2009Hankson 的趣味题[唯一分解定理|暴力]
题目描述 Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson.现 在,刚刚放学回家的 Hankson 正在思考一个有趣的问题. 今天在课堂上,老师讲 ...
- 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 ...
- HDU 6069 Counting Divisors(唯一分解定理+因子数)
http://acm.hdu.edu.cn/showproblem.php?pid=6069 题意: 思路: 根据唯一分解定理,$n={a_{1}}^{p1}*{a2_{}}^{p2}...*{a_{ ...
- Irrelevant Elements UVA - 1635 二项式定理+组合数公式+素数筛+唯一分解定理
/** 题目:Irrelevant Elements UVA - 1635 链接:https://vjudge.net/problem/UVA-1635 题意:給定n,m;題意抽象成(a+b)^(n- ...
- UVA - 10375 Choose and divide[唯一分解定理]
UVA - 10375 Choose and divide Choose and divide Time Limit: 1000MS Memory Limit: 65536K Total Subm ...
随机推荐
- UVALive - 4867 —— dp
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- Program received signal SIGSEGV, Segmentation fault.
GDB调试的时候出现了: Program received signal SIGSEGV, Segmentation fault.(程序收到信号SIGSEGV,分段故障) SIGSEGV:在POSIX ...
- 程序移植到VS2010,编译成功但是无法启动lib文件
今天遇到的这个问题,是由于解决方案下有多个项目,其中包含生成库的项目,也有可执行程序的项目 解决方法:邮件解决方案,属性-通用属性-启动项目进行设置就OK了,我的是设置单启动项目为包含可执行程序的项目 ...
- 组合数学中的常见定理&组合数的计算&取模
组合数的性质: C(n,m)=C(n,n-m); C(n,m)=n!/(m!(n-m)!); 组合数的递推公式: C(n,m)= C(n-1,m-1)+C(n-1,m); 组合数一般数值较大,题目会 ...
- 【CQ18高一暑假前挑战赛3】标程
[A:LCM] #include<bits/stdc++.h> using namespace std; #define ll long long int main() { ll a,b, ...
- Piggy-Bank(复习完全背包)
传送门 题目大意: 有一个存钱的储存罐,给你它存满钱之前和之后的重量,和几类硬币的面值和重量. 求装满储钱罐时最小能得到多少钱. 题解:完全背包变形. 因为要求最小 一开始赋值大数. code: #i ...
- poj1639顶点度限制生成树
题目:http://poj.org/problem?id=1639 对根的度数有限制的最小生成树: 先忽略根,跑最小生成树,得到几个连通块,再一一与根连上: 然后在限制内用根连出去的边来使生成树更小, ...
- hibernate 学习 一 基本概念
1: Hibernate对JDBC进行封装,以面向对象的方式对关系型数据库进行操作. 2: Hibernate的配置文件: hibernate.properties 或者 hibernate.c ...
- linux drwxr-xr-x 什么意思
第一位表示文件类型. d:是目录文件, l:是链接文件, -:是普通文件, p:是管道 第2-4位表示这个文件的属主拥有的权限,r是读,w是写,x是执行.(其中r是4,w是2,x是1) 第5-7位表示 ...
- 5、overflow、hover
一.overflow 1.属性介绍 说明: 这个属性定义溢出元素内容区的内容会如何处理.如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机制.因此,有可能即使元素框中可以放下所有内容也会 ...