GCD

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.

Input

The first line of input is an integer T(T<=100) representing the number of test cases. The following T lines each contains two numbers N and M (2<=N<=1000000000, 1<=M<=N), representing a test case.

Output

For each test case,output the answer on a single line.

Sample Input

3
1 1
10 2
10000 72

Sample Output

1
6
260

题意:

找出在1 << x << n && gcd(x, n) >= m总共有多少x符合条件。

思路:

欧拉函数的一题;
1 首先推导一下,我们假设gc = gcd(x, n),那么有a = x / gc, b = n / gc,因为gc已经是最大公约数了,所以gcd(a, b) = 1, 所以a, b互质。
2 因为x <= n, 所以a <= b所以只要求出小于b的数中与b互质的数有多少就行了。
3 想要求出答案的话,首先要求出b,所以就要求出gc了,然后就可以去枚举了,因为n很大,那就用根号,枚举1 <= i <= sqrt(n)就行了。
4 在主函数中,有三个if,第一个因为既然是最大公因数,那么n可以整除i了,后两个因为gc >= m(题目中有说),所以i >= m,因为我们枚举的是sqrt(i)的前一半,所以需要两个if了。最后计算欧拉数相加就行了。

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll Eular(ll n) {
    ll res = n;
    for (ll i = 2; i * i <= n; i++) {
        if (n % i == 0) res = res / i * (i - 1);
        while (n % i == 0) n /= i;
    }
    if (n > 1) res = res / n * (n - 1);
    return res;
}
int main() {
    ios::sync_with_stdio(false);
    ll t, n, m;
    scanf("%d", &t);
    while (t--) {
        ll sum = 0;
        scanf("%lld %lld", &n, &m);
        for (int i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                if (i >= m) sum += Eular(n / i);
                if (i * i != n && n / i >= m) sum += Eular(i);
            }
        }
        printf("%lld\n", sum);
    }
    return 0;
}