HDU2588 GCD

Problem

Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.

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.

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

Solution

设p=(X,N) (1<=x<=n),存在a,b,使得ap=X,bp=N,易知(a,b)=1。

问题转化为对于每一个p>=M,存在多少对a,b,求总的数量。

枚举p|N(p>=M),可以得到b=N/p,由于ab互质,ab对的数量为euler(N/p)。

由于p与N/p对称,枚举根号的量即可。

代码是用的质因数分解后枚举。

Code

#include<stdio.h>
#include<set>
#include<iostream>
#include<stack>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>

#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#ifdef io_opt
#define scanf sb
#define printf sb
#endif
typedef long long ll;
typedef __int128 lll;
typedef double db;
using namespace std;
#define eps 0.000000001
const int PN = 100000;
int pn;
bool ipr[PN + 10];
int pri[PN / 5];
int phi[PN + 10];

void prime() {
    memset(ipr, true, sizeof(ipr));
    ipr[1] = false;
    int N = sqrt(PN) + 0.5;
    for (int i = 2; i <= N; i++) {
        if (ipr[i]) {
            int d = i == 2 ? i : 2 * i;
            for (int j = i * i; j <= PN; j += d) {
                ipr[j] = false;
            }
        }
    }
    for (int i = 1; i <= PN; i++) {
        if (ipr[i]) pri[++pn] = i;
    }
}

void eprime() { //not verify
    memset(ipr, true, sizeof(ipr));
    ipr[1] = false;
    phi[1] = 1;
    for (int i = 2; i <= PN; i++) {
        if (ipr[i]) pri[++pn] = i, phi[i] = i - 1;
        for (int j = 1; j <= pn && pri[j] * i <= PN; j++) {
            ipr[pri[j] * i] = false;
            if (i % pri[j]) phi[i * pri[j]] = phi[i] * phi[pri[j]];
            else {
                phi[i * pri[j]] = phi[i] * pri[j];
                break;
            }
        }
    }
}

int euler_phi(int n) {
    int ans = n;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
}

ll speed(ll a, ll b, ll p) {
    ll cur = a, ans = 1;
    while (b) {
        if (b & 1) ans = ans * cur % p;
        cur = cur * cur % p;
        b >>= 1;
    }
    return ans % p;
}

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

int T, n, m, cnt, ans;
int a[100020], b[100020];

void fj(int t) {
    cnt = 0;
    for (int i = 1; i <= pn && pri[i] * pri[i] <= t; i++) {
        if (t % pri[i] == 0) a[++cnt] = pri[i], b[cnt] = 0;
        while (t % pri[i] == 0) {
            b[cnt]++;
            t /= pri[i];
        }
    }
    if (t > 1) a[++cnt] = t, b[cnt] = 1;
    if (cnt == 0) a[1] = 1, b[1] = 1;
}

void dfs(int t, int cur) {
    if (t == cnt + 1) {
        if (cur >= m) {
            ans += euler_phi(n / cur);
        }
        return;
    }
    dfs(t + 1, cur);
    for (int i = 1; i <= b[t]; i++) {
        cur *= a[t];
        dfs(t + 1, cur);
    }
}

int main() {
    io_opt;
    eprime();
    cin >> T;
    while (T--) {
        cin >> n >> m;
        ans = 0;
        fj(n);
        dfs(1, 1);
        cout << ans << endl;
    }
    return 0;
}


posted @ 2021-01-21 17:10  CCWUCMCTS  阅读(42)  评论(0编辑  收藏  举报