hdu(5505)——GT and numbers

比赛的时候一直迷。。。应该手模一下的。。

题意:

问题描述
给出两个数NNMMNN每次可以乘上一个自己的因数变成新的NN。
求最初的NNMM至少需要几步。
如果永远也到不了输出-11
输入描述
第一行读入一个数TT表示数据组数。
接下来TT行,每行两个数NNMMT\leq1000T1000, 1\leq N \leq 10000001N1000000,1 \leq M \leq 2^{63}1M263.

注意M的范围。hack时建议输出最后一行的行末回车;每一行的结尾不要输出空格。
输出描述
对于每组数据,输出一个数表示答案。
输入样例
3
1 1
1 2
2 4
输出样例
0
-1
1
思路:

首先把两个整数分解开来,然后先把一些特例判掉,然后去分别判断两个数的因子数量的不同个数,如果不同,对于某一个AA的质因数的次数。为了加速接近BB,它一定是每次翻倍,最后一次的时候把剩下的加上。

手模了一下,发现每次质因子都是扩大2倍,所以一直不停的乘以2就好,然后去找出所有质因子中进行次数最多的那个就好。

*hack点,很多人没有注意到范围是2^63次,所以这里要开unsigned __in64 才行,因为有符号的话范围刚好是2^63-1。

哦 还有map,vector没清零导致我一开始wa了几次。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
using namespace std;
typedef unsigned __int64 LL;
LL n,m;
vector<LL> a1,a2,cou;
map<LL,LL> mp1,mp2,mp;
void prime(LL x,int f){
	LL t=2;
	while(x!=1){
		bool ff=false;
		while(x%t==0){
			if(!f&&!ff) a1.push_back(t),ff=1;
			else if(f&&!ff) a2.push_back(t),ff=1;
			if(!f) mp1[t]++;
			else if(f) mp2[t]++;
			x=x/t;
		}
		t++;
	}
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		mp1.clear(); mp2.clear();
		mp.clear();
		a1.clear(); a2.clear();
		cou.clear();
		scanf("%I64u%I64u",&n,&m);
		if(n==1&&m!=1){
			printf("-1\n");
			continue;
		}
		if((n==1&&m==1)||(n==m)){
			printf("0\n");
			continue;
		}
		prime(n,0);
		prime(m,1);
		if(a1.size()!=a2.size()){
			printf("-1\n");
			continue;
		}
		int flag=1;
		for(int i=0;i<a1.size();i++){
			LL t1=a1[i],t2=a2[i];
			if((!mp1[t1]&&mp2[t2])||(mp1[t1]&&!mp2[t2])){
				printf("-1\n");
				flag=0;
				break;
			}
		}
		if(!flag) continue;
		int ff=1;
		for(int i=0;i<a1.size();i++){
			LL t=a1[i];
			LL num1=mp1[t],num2=mp2[t];
			if(num1>num2){
				ff=0;
				break;
			}
			LL tmp=num1;
			if(tmp==num2){
				mp[t]=0; continue;
			}
			int nn=0;
			for(int j=1; ;j++){
				tmp=tmp*2;
				nn++;
				if(tmp>=num2){
					mp[t]=nn;
					break;
				}
			}
		}
		if(!ff){
			printf("-1\n");
			continue;
		}
		LL lmax=0;
		#if 1
		for(int i=0;i<a1.size();i++){
			LL t=a1[i];
			lmax=max(lmax,mp[t]);
		}
		printf("%I64u\n",lmax);
		#endif
	}
}
/*
12
6 12

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值