题意:
给出一个分数A/B,询问最小的进制下使得A/B的小数是有穷的
思路:
观察一下,发现所谓的k进制就是对B除一个k,然后B要整除A,则B不能有A没有的素因子。然后就可以先求个gcd,对B/gcd进行大素数分解,素因子的乘积就是答案。
参考代码:
#include <stdio.h>
#include <random>
#include <time.h>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
namespace pollard_rho {
const int C = 2307;
const int S = 10;
typedef pair<ll, int> pli;
mt19937 rd(time(0));
vector<ll> ve;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll mul(ll a, ll b, ll mod) {
ll ans = 0;
a %= mod;
while (b) {
if (b & 1)
ans = (ans + a) % mod;
b >>= 1;
a = (a << 1) % mod;
}
return ans;
}
/*ll mul(ll a, ll b, ll mod) {
return a * b % mod;
}*/
ll power(ll a, ll b, ll mod) {
ll res = 1;
a %= mod;
while (b) {
if (b & 1)res = mul(res, a, mod);
a = mul(a, a, mod);
b >>= 1;
}
return res;
}
bool check(ll a, ll n) {
ll m = n - 1, x, y;
int j = 0;
while (!(m & 1))m >>= 1, j++;
x = power(a, m, n);
for (int i = 1; i <= j; x = y, i++) {
y = mul(x, x, n);
if (y == 1 && x != 1 && x != n - 1)return 1;
}
return y != 1;
}
bool miller_rabin(ll n) {
ll a;
if (n == 1)return 0;
if (n == 2)return 1;
if (!(n & 1))return 0;
for (int i = 0; i < S; i++)if (check(rd() % (n - 1) + 1, n))return 0;
return 1;
}
ll pollard_rho(ll n, int c) {
ll i = 1, k = 2, x = rd() % n, y = x, d;
while (1) {
i++;
x = (mul(x, x, n) + c) % n, d = gcd(y - x, n);
if (d > 1 && d < n)return d;
if (y == x)return n;
if (i == k)y = x, k <<= 1;
}
}
void findfac(ll n, int c) {
if (n == 1)return;
if (miller_rabin(n)) {
ve.push_back(n);
return;
}
ll m = n;
while (m == n)m = pollard_rho(n, c--);
findfac(m, c);
findfac(n / m, c);
}
vector<pli> solve(ll n) {
vector<pli> res;
ve.clear();
findfac(n, C);
sort(ve.begin(), ve.end());
for (auto x:ve) {
if (res.empty() || res.back().first != x)res.push_back({x, 1});
else res.back().second++;
}
return res;
}
}
using namespace pollard_rho;
map<ll,int>mp;
int main() {
ll a, b;
scanf("%lld%lld", &a, &b);
ll gcd=__gcd(a,b);
b/=gcd;
vector<pli> v = solve(b);
ll res = 1;
for (int i = 0; i < v.size(); i++){
res*=v[i].first;
}
printf("%lld\n", res > 1 ? res : 2);
return 0;
}