HDU 4497 GCD and LCM(数学)

来源:互联网 发布:淘宝一钻店铺值多少钱 编辑:程序博客网 时间:2024/06/06 12:53

题目链接:Click here~~

题意:

问有多少个三元组 {x,y,z} ,使得 gcd(x,y,z) = G && lcm(x,y,z) = L。(顺序不同视为不同方案)

解题思路:

开始没注意括号里的条件,纠结了一天。

之前和队友 yzwsm 讨论过类似的二元组的问题,记得当时提到过将 G 和 L 分解质因子的方法,于是做这题时一下就联想到了。

首先一定有 G | L,在这个条件下,将两个数分解质因子,则一定能得到相同的质因子,且只是指数不同。(Note: 指数可以为 0 & 指数相同的项可以忽略)

即有 G = p1^a1 * p2^a2 * p3^a3 ……, L = p1^b1 * p2^b2 * p3^b3 ……(ai <= bi)。

由于方案的计数符合乘法原理,所以我们只需要考虑对于某个 pi 的方案数,最后相乘即可。

那么对于某个pi,第三个数的取值范围一定是 [a,b],我们分情况来考虑第三个数是否会等于a or b。

1、如果不等于,ans1 = A(3,2) * (b-a-1)。(Note:[a+1,b-1]  =>  cnt = b-a-1)

2、如果等于,ans2 = C(3,1) * 2。

相加可化简为 ans = 6 * (b-a)。


还可以用容斥来考虑,转下。


另一种思考:容斥原理,对于p1,一共有(t1+1)^3种,但是没有最高位t1的选法是不合法的,减去,一共有t1^3种选法不合法,没有最低位0的选法是不合法的,也是t1^3,发现多减了,所以加上多减的既没有最高位也没有最低位的(t1-1)^3,通过化简得6*t1`````


#include <vector>#include <stdio.h>#include <string.h>using namespace std;vector< pair<int,int> > v1,v2;void get_pp(int g,int l){    v1.clear();    v2.clear();for(long long i=2;i*i<=l;i++){int point_cnt1 = 0, point_cnt2 = 0;while(g % i == 0){g /= i;point_cnt1 ++;}while(l % i == 0){l /= i;point_cnt2 ++;}if(point_cnt1 != point_cnt2){v1.push_back(make_pair(i,point_cnt1));v2.push_back(make_pair(i,point_cnt2));}}    if(l != 1 && g != l){v1.push_back(make_pair(l,0));v2.push_back(make_pair(l,1));}}long long solve(int g,int l){    if(l % g != 0)        return 0;    get_pp(g,l);long long ans = 1;for(int i=0;i<(int)v1.size();i++)ans *= 6 * (v2[i].second - v1[i].second);return ans;}int main(){int T,gcd,lcm;scanf("%d",&T);while(T--){scanf("%d%d",&gcd,&lcm);printf("%I64d\n",solve(gcd,lcm));}return 0;}


原创粉丝点击