有限小数
有限小数
给定三个整数 ,请你计算十进制表示下的 的结果在 进制下是否为有限小数。
输入格式
第一行包含整数 ,表示共有 组测试数据。
每组数据占一行,包含三个整数 。
输出格式
每组数据输出一行结果,如果 的结果在 进制下是有限小数,则输出 YES ,否则输出 NO 。
数据范围
前五个测试点满足 。
所有测试点满足 ,,,。
输入样例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
解题思路
对于,假设已经约分为最简分式,且只考虑小数的部分(即有,如果只需把整数部分去掉就可以),如果在进制下是一个有限小数,那么有,在十进制下表示就是。现在令左右两式同时乘上,得到,可以发现等式右边的是一个整数,因此也是一个整数,又因为已经是最简分式,因此有。
因此在进制下能用位来表示有限小数。
下面来推在进制下能用位来表示有限小数。
首先对于,一定是一个小于的数,这是以为,对进行放缩,取,有
现在令左右两边乘以,得到,其中等式右边的是一个整数,是一个小于的数,即得到进制下的第位数。把去掉,剩下的数继续乘上一个,即可得到进制下的第位数,以此类推,一共进行次,就可以得到位的进制数,因为,所有在等式左右两边乘以后,等式右边得到的就只有一个整数而没有小数,意味着可以转换为有限的进制数。因此有在进制下能用位来表示有限小数。
因此在进制下能用位来表示有限小数。
因此可以通过来判断在进制下是否为有限小数。先将约分,然后判断约分后的的质因子是否包含在的质因子内,这里如果用质因数分解会超时,因此需要用辗转相除法来判断,每次求,如果而说明,在进制下为无限小数。然后还会卡常数,需要优化,即每次求出后,需要一次性把用来除干净。
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/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16413097.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效