题目大意:给你两个数N和M,N每次可以乘以N的一个因数变成一个新的N,问至少进行多少步操作才能使得N变成M?如果不能变成M,那么输出-1。
分析:既然N每次乘以一个自己的因数,那么一开始组成N的质因数自始至终都不会改变,而且这些质因数上的指数只会增加(或者不变),不可能减小。那么我们就可以得到:组成N的所有质因数M都有,组成M的所有质因数N都有,也就是说N和M的质因数集合是一样的。而且这道题目N比较小,M比较大,那么我们优先分解N。对于N的每个质因数p,要保证M能够被p整除,而且M能够被N的所有质因数除干净。对于N的一个质因数P,不妨设N相对于P的指数是k,M相对于P的指数是s,那么首先需要保证的是k是小于等于s的。然后,为了使得k尽快变成s,那么k每次最多乘以2,那么至少需要ceil( log2( s / k ))步,然后把所有的质因数P需要的步数中取出最大值,就是结果!
代码:
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define maxn 1000+10
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define mp make_pair
#define FI first
#define SE second
#define IT iterator
#define PB push_back
#define Times 10
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double eps = 1e-10;
const double pi = acos(-1.0);
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;
inline void RI(int& x)
{
x=0;
char c=getchar();
while(!((c>='0'&&c<='9')||c=='-'))c=getchar();
bool flag=1;
if(c=='-')
{
flag=0;
c=getchar();
}
while(c<='9'&&c>='0')
{
x=x*10+c-'0';
c=getchar();
}
if(!flag)x=-x;
}
//--------------------------------------------------
int tot=0;
int prime[maxn];
bool isprime[maxn];
void init(int n){
for(int i=2;i<=n;i++){
if(!isprime[i])
prime[tot++]=i;
for(int j=0;1ll*prime[j]*i<=n;j++){
isprime[prime[j]*i]=true;
if(i%prime[j]==0)break;
}
}
}
int solve(int n,ll m){
int maxx=0;
for(int i=0;i<tot&&prime[i]<=n;i++)
if(n%prime[i]==0){
int k=0,s=0;
if(m%prime[i])return -1;
while(n%prime[i]==0){
k++;
n/=prime[i];
}
while(m%prime[i]==0){
s++;
m/=prime[i];
}
if(k>s)return -1;
maxx=max(maxx,(int)ceil(log(1.0*s/k)/log(2)));
}
if(n>1){
if(m%n)return -1;
int k=1,s=0;
while(m%n==0){
s++;
m/=n;
}
maxx=max(maxx,(int)ceil(log(1.0*s)/log(2)));
}
if(m>1)return -1;
else return maxx;
}
int main(){
//freopen("d:\\acm\\in.in","r",stdin);
init(1000);
int t;
scanf("%d",&t);
while(t--){
int n;
ll m;
scanf("%d %lld",&n,&m);
printf("%d\n",solve(n,m));
}
return 0;
}