[GDUT 决赛]--GCD,LCM——我是好人(数论)

 

Description

众所周知,我是好人!
所以不会出太难的题,题意很简单 给你两个数n和m,问你有多少对正整数对最大公约数是n,最小公倍数是m
最后友情提供解题代码(我真是太好人了)

void solve()

{

    long long n, m;

    scanf("%lld%lld", &n, &m);

    int ans = 0;

    for (long long i = 1; i <= m; i++)

    {

        for (long long j = i; j <= m; j++)

        {

            if (gcd(i, j) == n && lcm(i, j) == m) ans++;

        }

    }

    printf("%d\n", ans);



}

 

祝大家AC愉快!最好AK,送某扬兑现诺言^_^

Input
输入第1行是一个整数T,表示共T组数据。 接下来是T组数据,每组数据占1行,每一行有2个整数n,m(1 <= n, m <= 10000000000),两个数由一个空格隔开。

Output
结果输出T行,对应T组数据。(T<=100)
每行输出这样的正整数对有多少对(看我多好人,不用你们输出所有整数对)

Sample Input

3
1 1
7 10086
4 16

 

Sample Output

1
0
1

 

解题思路:(1)a,b 两数的最大公约数是n,最小公倍数是m,m 其实就是 n 乘以 a,b 各自特有的因子.那么

     肯定就有 m % n ==0 . 换句话说 如果 m % n !=0 那么 输出 就是0; 

     (2)如果n==m直接输出1,两个数相等且等于m;

     (3)设GCD = x,a = k1*x, b = k2*x,因为要使得GCD为x,那么k1,k2要互质,否则的话(假设公因子为c)求得的GCD=x*c,

     那么LCM = k1*k2*x,所以m/n=k1*k2,只要找k1,k2满足该式子就行,所以从1开始到根号m/n,找k1*k2=m/n,

     且两个互质 即GCD(k1,k2)==1 即可,那么复杂度Tn=O(√(m/n)),注意数据开long long!

代码如下:

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <algorithm>

 4 #include <cmath>

 5 using namespace std;

 6 typedef long long LL;

 7 

 8 LL gcd(LL a, LL b){

 9     return !b ? a : gcd(b, a%b);

10 }

11 LL Search(LL n)

12 {

13     LL i, tmp, cnt = 0;

14     for (i = 1; i <= (double)sqrt(n*1.0); i++){

15         if (!(n%i)){

16             //能整除才拆开计算,避免不必要的错误运算

17             tmp = n / i;

18             if (gcd(i, tmp) == 1) cnt++;

19         }

20     }

21     return cnt;

22 }

23 int main()

24 {

25     LL n, m, tmp;

26     int t;

27     scanf("%d", &t);

28     while (t--){

29         scanf("%lld%lld", &n, &m);

30         if (m%n){

31             printf("0\n");

32             continue;

33         }

34         if (n == m){

35             printf("1\n");

36             continue;

37         }

38         tmp = m / n;

39         printf("%lld\n", Search(tmp));

40     }

41     return 0;

42 }
View Code

 

你可能感兴趣的:(GC)