Choose and divide UVA - 10375(筛素法+唯一分解定理的应用)

  通过题目给的定义C(m,n)=m!/(n!(m-n)!),以及题目要求计算的C(p,q)/C(r,s)联立可得

    p!s!(r-s)!/q!r!(p-q)!

  看到这个式子,我们可以分析一下,我们可以将每个阶乘,都通过唯一分解定理将它们分解

  (具体教程可见:https://blog.csdn.net/qq_39439314/article/details/78270905)

  所以,首先我们应该先求出10000以内的所有素数,然后通过唯一分解定理将各个阶乘都分解,求出所有存在的可用质数以及对应的质数的指数

  p!s!(r-s)!/q!r!(p-q)!分母那一部分的阶乘分解时,对应质数增加时我们可以乘以一个-1,而分子对应的分解时,我们可以乘以一个1

  最后再将所有的pow(质数,对应指数)相乘,得到相应的结果,结果保留五位小数。

 1 #include<iostream>
 2 #include<string.h>
 3 #include <iomanip>
 4 #include<cmath>
 5
 6 typedef long long ll;
 7 const int maxn = 10000 + 10;
 8
 9 int primes[maxn];
10 bool p[maxn];
11 int e[maxn];
12 int tol = 0;
13
14 using namespace std;
15
16 void find_primes(int n);
17 void add_factorial(int n, int d);
18
19 int main()
20 {
21     ios::sync_with_stdio(false);
22     cin.tie(0);
23     cout.tie(0);
24
25     int p, q, r, s;
26     find_primes(maxn);//用筛素法打出素数表
27
28     while (cin >> p >> q >> r >> s)
29     {
30         memset(e, 0, sizeof(e));
31         add_factorial(p, 1);
32         add_factorial(s, 1);
33         add_factorial(r-s, 1);
34         add_factorial(q, -1);
35         add_factorial(r, -1);
36         add_factorial(p-q,-1);
37
38         double total = 1;
39
40         for (int i = 0; i < tol; i++)
41             total *= pow(primes[i], e[i]);
42         cout << fixed << setprecision(5) << total << endl;
43     }
44
45
46     return 0;
47 }
48
49 void find_primes(int n)//筛素法
50 {
51     memset(p, false, sizeof(p));
52
53     for (int i = 2; i <= n; i++)
54     {
55         if (!p[i])
56         {
57             primes[tol++] = i;
58             for (int j = i * i; j <= n; j += i)
59                 p[j] = true;
60         }
61     }
62 }
63
64 void add_factorial(int n, int d)//唯一分解定理对n!质因数分解的应用
65 {
66     for (int i = 0; i < tol; i++)
67     {
68         if (primes[i] > n)
69             break;
70         ll t = primes[i];
71         while (t <= n)
72         {
73             e[i] += d * n / t;
74             t *= primes[i];
75         }
76     }
77 }

原文地址:https://www.cnblogs.com/cdplay/p/9419931.html

时间: 2024-10-12 07:35:56

Choose and divide UVA - 10375(筛素法+唯一分解定理的应用)的相关文章

uva 10791 Minimum Sum LCM ( 唯一分解定理 )

使用唯一分解定理的时候不一定要打出素数表,这句话是相对上一篇来讲的.做这道题目之前我对唯一分解定理方法的理解不完全. 现在多想到了一些 唯一分解,将当前需要分解的n用因子将其分解表达.需要试因子. 因子的枚举应该是从2开始(从1开始没有意义),当当前数字n可以整除当前因子i时,就使其不断除以i,直到不能整除. 这个步骤实际上已经在根本上避免了出现像4.6这种因子在唯一分解式中的出现--之前的因子2和3已经将其代替了.所以可证明唯一分解时并不一定需要构造素数表 针对本题来说,最小公倍数的最小和,有

UVA - 11728 Alternate Task (唯一分解定理)

Little Hasan loves to play number games with his friends.One day they were playing a game where one of them will speak out a positive numberand the others have to tell the sum of its factors. The first one to say itcorrectly wins. After a while they

UVA 10375 Choose and divide(数论)

The binomial coefficient C(m,n) is defined as m! C(m,n) = -------- n!(m-n)! Given four natural numbers p, q, r, and s, compute the the result of dividing C(p,q) by C(r,s). The Input Input consists of a sequence of lines. Each line contains four non-n

【暑假】[数学]UVa 10375 Choose and divide

UVa 10375 Choose and divide 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19601 思路: maxn=10000 如果计算maxn!再保存的话显然装不下. 但答案由阶乘的积或商组成,所以可以用唯一分解定理求解.大题思路就是把目前答案的质因子的指数用数组e保存,乘除都对e操作. 需要注意的是筛法求素数优化后的写法. 代码: 1 #include<iostream> 2 #include

UVA 10375 Choose and divide(唯一分解定理)

这么大数的乘法.除法运算,肯定不能先全部乘起来,我的思路是计算出分子.分母上的每个数的个数(因为最大的数为10000,可以开一个数组记录个数). 利用了随机数方法终于知道错在哪了,中间如果出现连乘还是会溢出,这点没想到,以下是我的溢出代码: #include<stdio.h> #include<math.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<

10375 - Choose and divide(唯一分解定理的运用 eratosthenes构造素数表)

我觉得数学类的题目,每一道都有很好的解决方法,都很有保存的意义和价值. 这道题目里面,巧妙地运用了 唯一分解定理,辅以素数的eratosthenes筛法构造,很好地解决了题目.值得思考和深入的学习. #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; vector<int>

UVA - 10375 - Choose and divide (组合数)

题目传送:UVA - 10375 思路:用double存答案,不过要注意是边乘边除,这样不会爆double,还有记得乘的时候要把int转换成double AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #

筛素数法小结

筛选素数方法小结: 最简单的筛素数法方法就是从2开始,将所以2的倍数去掉,然后从3开始,将3的倍数去掉,依次进行下去即可.根据这样很容易写出代码,下面代码就是是筛素数法得到100以内的素数并保存到primes[]数组中. 1 const int MAXN = 100; 2 bool flag[MAXN]; 3 int primes[MAXN / 3], pi; 4 void GetPrime_1() 5 { 6 int i, j; 7 pi = 0; 8 memset(flag, false,

uva 10375 唯一分解定理 筛法求素数【数论】

唯一分解理论的基本内容: 任意一个大于1的正整数都能表示成若干个质数的乘积,且表示的方法是唯一的.换句话说,一个数能被唯一地分解成质因数的乘积.因此这个定理又叫做唯一分解定理. 举个栗子:50=(2^1)*(5^2) 题目一般的思路就是要把素数表打出来,eg上面的例子 e={1,0,2,0,0......} 下面是两个题目,仅说说大致的思想: 题目一: E=(X1*X3*X4* ...*Xk)/X2   判断E是不是整数 如果把(X1*X3*X4* ...*Xk)分解成素数相乘,将X2也分解成素