题意
东东在玩游戏“Game23”。
在一开始他有一个数字n,他的目标是把它转换成m,在每一步操作中,他可以将n乘以2或乘以3,他可以进行任意次操作。输出将n转换成m的操作次数,如果转换不了输出-1。
Input
输入的唯一一行包括两个整数n和m(1<=n<=m<=5*10^8).
Output
输出从n转换到m的操作次数,否则输出-1.
输入样例
Simple Input 1
120 51840
Simple Input 2
42 42
Simple Input 3
48 72
输出样例
Simple Output 1
7
Simple Output 2
0
Simple Output 3
-1
提示
分析
一道简单的思维题。
- 题目分析
两个数字从a转换,只能通过乘以2和3来实现。
显然,a和b之间一定满足以下条件:
- b一定能整除a
- b一定大于a的2倍或a的3倍或b等于a
- b一定能整除2或整除3
只要这些条件不满足,首先就肯定判定这两个数一定无法实现转换。
其次考虑,如果a和b之间可以转换,就代表着a乘以一个因子可以得到b。而这个因子只由多个2和3中的一个或两个组成。
所以,先得到这个因子,将该因子逐层整除。如果该因子只能整除2,则除以2;如果只能3,则除以3;如果两者皆可整除,则除以6。
直到该因子等于1,说明该因子符合要求;或出现2和3都无法整除时,说明该因子含有除2和3以外的因子,不符合要求。
在处理该因子的过程中记录转换次数,显然每除掉一个2或3就代表着转换时乘上一个2或3,则转换次数+1,而除掉一个6代表转换时需要乘以一个2和一个3,因此转换次数+2。
总结
- 我总是在拿到题的一开始想得很复杂👐🏼最开始几次提交都wa,搞得我一头雾水,结果洗了个澡出来就知道自己有多蠢了👋
- 注意a和b相等的特殊情况!
代码
//
// main.cpp
// lab1
//
//
#include <iostream>
#include <queue>
#include <map>
using namespace std;
int n = 0,m = 0,res = 0;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
//如果不能整除或本身小于n或小于2倍也小于3倍或本身无法整除2或3,肯定不行
//如果相等,直接输出0
if( m == n )
{
cout<<0<<endl;
}
else if( m % n != 0 || m < n ||( m < 2 * n && m < 3 * n) || (m % 2 != 0 && m % 3 != 0 ))
cout<<-1<<endl;
else
{
m /= n; //得到它们的商
//如果能转换,则商一定有且仅有2、3中的一个或两个相乘所得
while(1)
{
if( m % 2 == 0 && m % 3 == 0 ) //若同时能整除,直接除以6
{
m /= 6;
res += 2; //转换次数+2
}
else if( m % 2 == 0 ) //只能整除2
{
m /= 2;
res += 1;
}
else if( m % 3 == 0 ) //只能整除3
{
m /= 3;
res += 1;
}
else if( m % 2 != 0 && m % 3 != 0 ) //若都不能整除,说明无法转换
{
cout<<-1<<endl;
return 0;
}
if( m == 1 ) //若最后得到1,说明转换成功
{
cout<<res<<endl;
return 0;
}
else if( m < 1 ) //否则失败
{
cout<<-1<<endl;
return 0;
}
}
}
return 0;
}