题目大意:给你两个数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; }