题目

来源:ACwing4484-有限小数

给定三个整数 p,q,b,请你计算十进制表示下的 p/q 的结果在 b进制下是否为有限小数。

输入格式

第一行包含整数 TT,表示共有 TT 组测试数据。

每组数据占一行,包含三个整数 p,q,b。

输出格式

每组数据输出一行结果,如果 p/q的结果在 b 进制下是有限小数,则输出 YES,否则输出 NO

数据范围

前五个测试点满足 1≤T≤101≤T≤10。
所有测试点满足 1≤T≤105,0≤p≤1018,1≤q≤1018,2≤b≤1018。

输入样例1:

1
2
3
2
6 12 10
4 3 10

输出样例1:

1
2
YES
NO

输入样例2:

1
2
3
4
5
4
1 1 2
9 36 2
4 12 3
3 5 4

输出样例2:

1
2
3
4
YES
YES
YES
NO

笔者解析

本题为ACwing的周赛困难题。所运用到的主要知识为:

小数进制转换计算

十进制小数→R进制小数

乘R取整顺序法:乘基数取整,连续乘以基数,并取其整数,直到积为零或达到所要求的精度时,将所得整数正序排列即可。

由此题将小数转换为二进制,可看出是小数不断的乘2,取最整数位为结果位,取小数位为下一个继续计算位,直到下一计算位最终取值为0。

img

约分

本题有两个地方需要约分

  1. 初始的p/q,要进行初始约分去除两数之间的公因数。

  2. 要拿q与d进行不断约分,每次找到最大公因数g,不断使用q/=d,直到q与d之间的最大公约数为g=1

    为什么要这样计算呢?因为我们的q一定要能被d的次方整除,才可以被转换成其它进制的有限小数,使用d的次方,也就需要不断要取得新的q与d的g值。

笔者代码

java版本

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(bufferedReader.readLine());;
while (n-->0){
int []arr = new int[n];
String []a = bufferedReader.readLine().split(" ");
long p= Long.parseLong(a[0]);
long q= Long.parseLong(a[1]);
long b= Long.parseLong(a[2]);
if(p%q==0||p == 0){System.out.println("YES");continue;}
long y = gcd(p,q);
p/=y;q/=y;
long g ;

while(true){
g = gcd(q,b);
if(g == 1){ break;}
while(q%g==0){ q /= g; }
}

if(q == 1){
System.out.println("YES");
continue;
}else {
System.out.println("NO");
}
}
bufferedReader.close();
}
public static long gcd(long a,long b){
if(a%b == 0){
return b;
}
return gcd(b,a%b);
}
}

c++ y总版

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
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

LL gcd(LL a, LL b)
{
return b ? gcd(b, a % b) : a;
}

int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
LL p, q, b;
scanf("%lld%lld%lld", &p, &q, &b);
LL d = gcd(p, q);
q /= d;
while (q > 1)
{
d = gcd(q, b);
if (d == 1) break;
while (q % d == 0) q /= d;
}

if (q == 1) puts("YES");
else puts("NO");
}

return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/3628074/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。