hdu_4497GCD and LCM(合数分解)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4497

GCD and LCM

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2151    Accepted Submission(s): 955

Problem Description

Given two positive integers G and L, could you tell me how many solutions of (x, y, z) there are, satisfying that gcd(x, y, z) = G and lcm(x, y, z) = L? 
Note, gcd(x, y, z) means the greatest common divisor of x, y and z, while lcm(x, y, z) means the least common multiple of x, y and z. 
Note 2, (1, 2, 3) and (1, 3, 2) are two different solutions.

Input

First line comes an integer T (T <= 12), telling the number of test cases. 
The next T lines, each contains two positive 32-bit signed integers, G and L. 
It’s guaranteed that each answer will fit in a 32-bit signed integer.

Output

For each test case, print one line with the number of solutions satisfying the conditions above.

Sample Input

2
6 72
7 33

Sample Output

72
0

Source

2013 ACM-ICPC吉林通化全国邀请赛——题目重现

题意:给出三个数的最大公约数和最小公倍数,让求abc这三个数可能的情况,注意ABC的位置不同算不同的情况

考虑先分解最小公倍数。合数分解后,再分解最大公约数,可知,如果最大公约数中有最小公倍数中没有的质因数因子的话,那么答案肯定为0

然后考虑每一个因子pi有设合数分解最小公倍数的个数为bi合数分解最大公约数的个数为bi

下面有两种考虑方法

  排列组合:易得三个数中的对于pi的情况必须有一个个数是bi,另一个是ai,然后就可以先选出两个位置一个bi一个ai然后最后一个位置上的个数一定介于ai和bi之间即(bi-ai-1)种情况。

所以最后的公式为ans *=  A(3,2)*(bi-ai-1) = 6*(bi-ai-1) ;

注意,如果先筛素数的时候筛到1^6 然后如果L除以最后一个素数的时候不等于1,那么说明它(L的最后一个因子)一定是大于10^6的一个素数,因为10^12 = 10^6^2 > x^2>y;如果y存在一个非素数的因子k的话,有k*t = y 且k>x,则t<x则t已经被筛掉了。所以剩下的因子一定是素因子。一开始没有考虑这种特殊情况wa掉了。。。

注意,还要注意只有当(bi-ai-1) 有意义的时候才可以计算,因为如果bi==ai的时候可以发现正确结果是对于这一位应该是只用一种情况,就是三个数都相等,所以要特判一下。。。。后来又因为这个wa了一次~~~~(>_<)~~~~

  容斥定理:同样是考虑每个因子,有所有的情况是每个位置都可以取(bi-ai+1)种情况即(bi-ai+1)^3,要减去没有bi个因子的情况和没有ai个因子的情况即2*(bi-ai)^3

然后发现减多了,要加上同时没有因子ai和bi的情况即(bi-ai-1)^3

这里同样要注意上面的注意。

 1 //合数分解
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define ll long long
 7 const int maxn = 1000005;
 8 int prime[maxn];
 9 bool pri[maxn];
10 int cnt;
11 void init()
12 {
13     cnt = 0;
14     pri[0] = pri[1] = 1;
15     //prime[0] = 2;
16     for(int i = 2; i < maxn; i++){
17         if(!pri[i]){
18
19             prime[cnt++] = i;
20             for(int j = i+i; j < maxn; j+=i)
21             {
22                 pri[j]=1;
23             }
24         }
25     }
26     return;
27 }
28 ll m1[10005],m2[10005];
29 ll c1[10005],c2[10005];
30 int main()
31 {
32     init();
33     int T;
34     ll G,L;
35     scanf("%d",&T);
36     while(T--)
37     {
38         memset(m1,0,sizeof(m1));
39         memset(c1,0,sizeof(c1));
40         memset(m2,0,sizeof(m2));
41         memset(c2,0,sizeof(c2));
42         scanf("%lld%lld",&G,&L);
43         int tm = 0;
44         bool in = 0;
45         bool fl = 1;
46         //printf("%d\n",prime[1]);
47         if(L%G) fl = 0;
48         for(int i = 0; i< cnt; i++){
49             while(prime[i]<=L&&L%prime[i]==0){
50                 L = L/prime[i];
51                 m2[tm] = prime[i];
52                 c2[tm]++;
53                 in = 1;
54             }
55             if(in) tm++;
56             in = 0;
57         }
58         if(L!=1){
59             m2[tm] = L;
60             c2[tm] = 1;
61             tm++;
62         }
63         for(int i = 0; i < tm; i++){
64             while(m2[i]<=G&&G%m2[i]==0){
65                 G = G/m2[i];
66                 m1[i] = m2[i];
67                 c1[i]++;
68             }
69             in = 0;
70         }
71         if(G!=1){
72            fl = 0;
73         }
74         /*puts("haha");
75         for(int i = 0; i < tm; i++){
76             printf("m1[%d]=%d; m2[%d]=%d;\n",i,m1[i],i,m2[i]);
77             printf("c1[%d]=%d; c2[%d]=%d;\n",i,c1[i],i,c2[i]);
78         }
79         */
80         if(fl==0) {puts("0"); continue;}
81         ll ans = 1;
82         for(int i = 0; i < tm; i++){
83             //需要特判当c1[i] =c2[i]的情况
84             ll E;
85             if(c1[i]==c2[i]) E = 0;
86             else E = c2[i]-c1[i]-1;
87             /*
88                 也可以用排列组合的想法,每次找到两个数包含首尾的两个值,然后中间的一个在从所有可能中选取一个。
89                 这样最后的公式就是A(3,2)*(c2[i]-c1[i]-1);
90                 所以
91                 if(c2[i]>c1[i]) ans = ans*6*(c2[i]-c1[i]-1);
92                     */
93             ans = ans*((c2[i]-c1[i]+1)*(c2[i]-c1[i]+1)*(c2[i]-c1[i]+1)-2*(c2[i]-c1[i])*(c2[i]-c1[i])*(c2[i]-c1[i])+E*E*E);
94         }
95         printf("%lld\n",ans);
96     }
97     return 0;
98 }
时间: 2024-12-19 11:25:18

hdu_4497GCD and LCM(合数分解)的相关文章

hdu 5317 合数分解+预处理

RGCDQ Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2818    Accepted Submission(s): 1108 Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more and m

HDU 5317 RGCDQ (合数分解+预处理)

题目链接:HDU 5317 RGCDQ 题意:定义函数F(x)为x的不同的素因子且小于等于x的个数,询问[l,r]区间中gcd(F(i),F(j))的最大值. 思路:暴力预处理出所有的合数分解结果,发现F(x)最大也只有7,之后就是暴力求出所有1到7出现次数的前缀和.询问的时候就打到O(1)了. AC代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #

pku1365 Prime Land (数论,合数分解模板)

题意:给你一个个数对a, b 表示ab这样的每个数相乘的一个数n,求n-1的质数因子并且每个指数因子k所对应的次数 h. 先把合数分解模板乖乖放上: for (int i = 2; ans != 1; ++i) { if (ans%i == 0) { num[cnt] = i; int k = 0; while (ans%i == 0){ ++k; ans /= i; } index[cnt++] = k; } if (i > 10000)break; } if (ans != 1){ num[

hdu 5428 The Factor(素数筛选合数分解)

题意:求一串数乘积的因子中的最小合数: 思路:比赛时枚举因子,枚举到两个时结束,估计超时,结果果然被叉了: 将每个数分解,取最小的两个质因子,若数目少于2,则不存在: #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; int t,n,m; int num[505]; const int MAXN=100000; int pr

UVA10892 - LCM Cardinality(分解质因子)

题目链接 题意:输入正整数n,统计有多少对正整数a <= b,满足lcm(a, b) = n. 思路:分解质因子,然后直接暴力求出对数 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; const int MA

HDU 4497 GCD and LCM(分解质因子+排列组合)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4497 题意:已知GCD(x, y, z) = G,LCM(x, y, z) = L.告诉你G.L,求满足要求的(x, y, z)有多少组,并且要考虑顺序. 思路:如果L%G != 0显然不存在这样的(x, y, z),相反肯定存在.具体做法就是将L/G分解质因子,得到:L/G = P1^t1 * P2^t2 * ... * Pk^tk,我们来考虑任意一个因子Pi^ti,此时(x/G, y/G, z/

UVA 10892 LCM Cardinality (分解因数+暴力)

LCM Cardinality A pair of numbers has a unique LCM but a single number can be the LCM of more than one possible pairs. For example 12 is the LCM of (1, 12), (2, 12), (3,4) etc. For a given positive integer N, the number of different integer pairs wit

HDU 4497 素数筛,合数分解

题意:给你两个数,G和L ,它们是一组数的GCD(最大公约数)和LCM(最小公倍数),求出满足条件的组合数,每个组合有三个数,排序不同,也算不同组合. L : p1^t1 * p2^t2 ... * pi^ti G: q1^s1 * q2^s2... * qi^si (pi和qii都是素数ii) G(最大公约数)里出现的所有数都要在L(最小公倍数)里出现,或者说L mod G=0,有人要问为什么了?其实仔细想想就清楚了,如果a,b,c的最小公倍数肯定可以被a,b,c任意一个整除,而他们的最大公约

51nod 1434 区间LCM (质因数分解)

分析:考虑从1到n所有数的质因数分解,记录每个质数的最高次数,同理从n+1循环到2n,如果循环到m时每个质因子的次数都不低于所记录的,则跳出循环,结果即为m.先预处理质数,复杂度为O(nlongn). 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=1000005;