(luogu1072) Hankson 的趣味题

原题链接

思路:

首先,由题意,\([x,b_0] = b1 \Rightarrow b_0|b_1\).

\(k_b = \frac{b_1}{b_0}\), 令 \(b_0 = tg\), 则 \(b_1 = k_btg\), 当 \((k_b,t)=1\) 时,\((x,b_0) = g\), \(x = k_bg\).

同时,\((x,a_0) = a_1 \Rightarrow a_1|x\).

\(x = k_aa_1\), \(a_0 = sa_1\), 则有 \((s,k_a) = 1\).

由上述一系列结论可以得到该题的算法:枚举 \(b_0\) 的所有因子作为 \(g\), 判定 \((k_b,t)=1\), 是否成立,然后求出 \(x\), 判定 \(a_1|x\) \((s,k_a)=1\) 是否成立即可.

时间复杂度为 \(O(n * \sqrt{b_0}log\ b_0)\)

代码:

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
#include <cstdio>
#include <cmath>
int gcd(int a,int b) {
while(b!=0) {
int m = a%b;
a = b;
b = m;
}
return a;
}

int main() {
int T;
scanf("%d",&T);
while(T--) {
int a0,a1,b0,b1;
scanf("%d %d %d %d",&a0,&a1,&b0,&b1);
int kb = b1/b0;
int ub = sqrt(b0); //枚举上界
int ans(0); //计数
for(int i(1);i<=ub;++i) {
if(b0%i==0) {
int g1 = i, g2 = b0/i; //两个因数
if(gcd(kb,g2)==1) {
int x = kb*g1;
if(x%a1==0 && gcd(x/a1,a0/a1)==1) {
++ans;
}
}
/*注意细节: g1可能等于g2,此时只算一个*/
if(g2!=g1 && gcd(kb,g1)==1) {
int x = kb*g2;
if(x%a1==0 && gcd(x/a1,a0/a1)==1) {
++ans;
}
}
}
}
printf("%d\n",ans);
}
return 0;
}