C. C. Blog

Security Research, Algorithm and Data Structure

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#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;
}


  • 本文作者: CCWUCMCTS
  • 本文链接: https://ccwucmcts.github.io/posts/38455/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!