一 原题
You are given several queries. Each query consists of three integers pp, qq and bb. You need to answer whether the result of p/qp/q in notation with base bb is a finite fraction.
A fraction in notation with base bb is finite if it contains finite number of numerals after the decimal point. It is also possible that a fraction has zero numerals after the decimal point.
The first line contains a single integer nn (1≤n≤1051≤n≤105) — the number of queries.
Next nn lines contain queries, one per line. Each line contains three integers pp, qq, and bb (0≤p≤10180≤p≤1018, 1≤q≤10181≤q≤1018, 2≤b≤10182≤b≤1018). All numbers are given in notation with base 1010.
For each question, in a separate line, print Finite if the fraction is finite and Infinite otherwise.
2 6 12 10 4 3 10
Finite Infinite
4 1 1 2 9 36 2 4 12 3 3 5 4
Finite Finite Finite Infinite
612=12=0,510612=12=0,510
43=1,(3)1043=1,(3)10
936=14=0,012936=14=0,012
412=13=0,13
二 分析
题意是说给你三个数p,q,b.问你分数p/q在b进制下是否是有穷小数。首先把q除去p,q的最大公约数得到新的q.p/q是有穷小数等价于新的q的素因子都是b的素因子。因为p,q,b最大都是max=10^18,直接分解素因子需要sqrt(max)次操作,会超时。我在比赛的时候想到的办法是求q和b的最大公约数t,只要分解q/t和t中较小的一个就可以了,复杂度就变成了两次开根。更多人选择的解法见下面代码,话说c++17已经自带了std::gcd函数,在头文件<numeric>里。
三 代码
#include <cstdio>
#include <numeric>
typedef long long LL;
using std::gcd;
int n;
LL p, q, b;
int main() {
scanf("%d", &n);
while (n--) {
scanf("%lld%lld%lld", &p, &q, &b);
q /= gcd(p, q);
while (true) {
LL g = gcd(q, b);
if (g == 1) break;
while (q % g == 0) q /= g;
}
if (q == 1) puts("Finite");
else puts("Infinite");
}
return 0;
}