题目链接 : http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=641&pid=1002
思路 :
N有若干个质因子, N = a^b * c^d * e^f......
M也有若干个质因子, M = a^(b+k) * c(d+k1) * e^(f+k2)......
N能到达M的条件是它们的质因子必须完全相同
N每次可以乘上它的若干个质因子, 直到这个质因子的幂次等于M这个质因子的幂次
考虑这样一个事实, N乘上某个质因子的a次幂后, 新的N可以乘上该质因子的2a次幂
故对于每个质因子, N的次数每次平方, cnt++, 直到大于等于M这个质因子的次数, 取最大的cnt即可
要注意的是M的范围会爆long long 所以要开unsigned long long
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long LL; const int MAXN = 1e6+10; const int PRI_NUM = 2e6+10; bool vis[PRI_NUM]; int prime[MAXN]; int factor_n[MAXN]; int factor_m[MAXN]; int prime_n[50]; int prime_m[50]; void Pre() { for(int i = 2; i <= PRI_NUM; i++) { if(vis[i] == 0) { for(int j = i+i; j <= PRI_NUM; j+=i) { vis[j] = 1; } } } int cnt = 0; for(int i = 2; i <= PRI_NUM; i++) { if(vis[i] == 0) { prime[cnt++] = i; } } } void Init() { memset(prime_n, 0, sizeof(prime_n)); memset(prime_m, 0, sizeof(prime_m)); } int main() { Pre(); int t; int n; LL m; scanf("%d", &t); while(t--) { Init(); scanf("%d %I64u", &n, &m); if(m == n) { printf("0\n"); continue; } if(m % n || n <= 1) { printf("-1\n"); continue; } int cnt = 0; for(int i = 0; i < MAXN; i++) { if(n == 1) break; if(n % prime[i] == 0) { factor_n[cnt] = prime[i]; while(n % prime[i] == 0) { n /= prime[i]; prime_n[cnt]++; } cnt++; } } if(n > 1) { factor_n[cnt] = n; prime_n[cnt] = 1; cnt++; } for(int i = 0; i < cnt; i++) { while(m % factor_n[i] == 0) { m /= factor_n[i]; prime_m[i]++; } } if(m > 1) { printf("-1\n"); continue; } int ans = 0; for(int i = 0; i < cnt; i++) { int k = 0; while(prime_n[i] < prime_m[i]) { prime_n[i] <<= 1; k++; } if(k > ans) ans = k; } printf("%d\n", ans); } return 0; }
另外看到一种很强的做法
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ULL; ULL Gcd(ULL a, ULL b) { ULL r; while(a % b) { r = a % b; a = b; b = r; } return b; } int main() { int t; ULL n, m; scanf("%d", &t); while(t--) { scanf("%I64u %I64u", &n, &m); int ans = 0; bool flag = 1; while(n != m) { if(m % n) { flag = 0; break; } ULL temp = Gcd(m / n, n); if(temp == 1) { flag = 0; break; } n *= temp; ans++; } if(flag == 1) { printf("%d\n", ans); } else printf("-1\n"); } return 0; }