有限小数
作者:互联网
有限小数
给定三个整数 $p,q,b$,请你计算十进制表示下的 $p/q$ 的结果在 $b$ 进制下是否为有限小数。
输入格式
第一行包含整数 $T$,表示共有 $T$ 组测试数据。
每组数据占一行,包含三个整数 $p,q,b$。
输出格式
每组数据输出一行结果,如果 $p/q$ 的结果在 $b$ 进制下是有限小数,则输出 YES ,否则输出 NO 。
数据范围
前五个测试点满足 $1 \leq T \leq 10$。
所有测试点满足 $1 \leq T \leq {10}^{5}$,$0 \leq p \leq {10}^{18}$,$1 \leq q \leq {10}^{18}$,$2 \leq b \leq {10}^{18}$。
输入样例1:
2 6 12 10 4 3 10
输出样例1:
YES NO
输入样例2:
4 1 1 2 9 36 2 4 12 3 3 5 4
输出样例2:
YES YES YES NO
解题思路
对于$\frac{p}{q}$,假设已经约分为最简分式,且只考虑小数的部分(即有$p < q$,如果$p > q$只需把整数部分去掉就可以),如果$\frac{p}{q}$在$b$进制下是一个有限小数,那么有${\left( {\frac{p}{q}} \right)}_b = 0.a_1a_2 \dots a_k$,在十进制下表示就是${\left( {\frac{p}{q}} \right)}_{10} = a_1 \cdot b^{-1} + a_2 \cdot b^{-2} + \dots + a_k \cdot b^{-k}$。现在令左右两式同时乘上$b^{k}$,得到$\left( {\frac{p}{q}} \right) \cdot b^{k} = a_1 \cdot b^{k-1} + a_2 \cdot b^{k-2} + \dots + a_k$,可以发现等式右边的$a_1 \cdot b^{k-1} + a_2 \cdot b^{k-2} + \dots + a_k$是一个整数,因此$\left( {\frac{p}{q}} \right) \cdot b^{k}$也是一个整数,又因为$\frac{p}{q}$已经是最简分式,因此有$q \mid b^{k}$。
因此$\frac{p}{q}$在$b$进制下能用$k$位来表示有限小数$\Rightarrow$$q \mid b^{k}$。
下面来推$\frac{p}{q}$在$b$进制下能用$k$位来表示有限小数$\Leftarrow$$q \mid b^{k}$。
首先对于$a_1 \cdot b^{k-1} + a_2 \cdot b^{k-2} + \dots + a_k$,一定是一个小于$1$的数,这是以为$0 \leq a_i < b$,对$a_i$进行放缩,取$a_i = b-1$,有$$\begin{align*} a_1 \cdot b^{-1} + a_2 \cdot b^{-2} + \dots + a_k \cdot b^{-k} &\leq \left( {b-1} \right) \times \left( {b^{-1} + b^{-2} + \dots + b^{-k}} \right) \\ &= \left( {b-1} \right) \times \frac{1 - b^{-k}}{b-1} \\ &= 1 - b^{-k} < 1 \end{align*}$$
现在令$\left( \frac{p}{q} \right) = a_1 \cdot b^{-1} + a_2 \cdot b^{-2} + \dots + a_k \cdot b^{-k}$左右两边乘以$b$,得到$\left( \frac{p}{q} \right) \cdot b = a_1 + a_2 \cdot b^{-1} + \dots + a_k \cdot b^{-k + 1}$,其中等式右边的$a_1$是一个整数,$a_2 \cdot b^{-1} + \dots + a_k \cdot b^{-k + 1}$是一个小于$1$的数,即得到$b$进制下的第$1$位数$a_1$。把$a_1$去掉,剩下的数继续乘上一个$b$,即可得到$b$进制下的第$2$位数$a_2$,以此类推,一共进行$k$次,就可以得到$k$位的$b$进制数,因为$q \mid b^{k}$,所有在等式左右两边乘以$b^k$后,等式右边得到的就只有一个整数而没有小数,意味着可以转换为有限的$b$进制数。因此有$\frac{p}{q}$在$b$进制下能用$k$位来表示有限小数$\Leftarrow$$q \mid b^{k}$。
因此$\frac{p}{q}$在$b$进制下能用$k$位来表示有限小数$\Leftrightarrow$$q \mid b^{k}$。
因此可以通过$q \mid b^{k}$来判断$p/q$在$b$进制下是否为有限小数。先将$p/q$约分,然后判断约分后的$q$的质因子是否包含在$b$的质因子内,这里如果用质因数分解会超时,因此需要用辗转相除法来判断,每次求$d = gcd \left( {q,b} \right)$,如果$d=1$而$q>1$说明$q \nmid b$,在$b$进制下为无限小数。然后还会卡常数,需要优化,即每次求出$d$后,需要一次性把$q$用$d$来除干净。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 LL gcd(LL a, LL b) { 7 return b ? gcd(b, a % b) : a; 8 } 9 10 int main() { 11 int tot; 12 scanf("%d", &tot); 13 while (tot--) { 14 LL p, q, b; 15 scanf("%lld %lld %lld", &p, &q, &b); 16 q /= gcd(p, q); 17 18 while (q > 1) { 19 LL d = gcd(q, b); 20 if (d == 1) break; 21 22 // 如果直接q /= d; 会被卡常数 23 // 一次除干净 24 while (q % d == 0) { 25 q /= d; 26 } 27 } 28 printf("%s\n", q == 1 ? "YES" : "NO"); 29 } 30 31 return 0; 32 }
参考资料
AcWing 4484. 有限小数(AcWing杯 - 周赛):https://www.acwing.com/video/3978/
标签:right,frac,进制,cdot,leq,有限小数 来源: https://www.cnblogs.com/onlyblues/p/16413097.html