P11130 【MX-X5-T2】「GFOI Round 1」Interstellar
题目背景
原题链接:https://oier.team/problems/X5C。
题目描述
你有一个正整数 x x x,你可以对它进行如下操作:
- 选择一个正整数
y
y
y,把
x
x
x 变为它的
gcd
(
x
,
y
)
\gcd(x, y)
gcd(x,y) 倍,即
x
←
x
×
gcd
(
x
,
y
)
x \gets x \times \gcd(x, y)
x←x×gcd(x,y)。
( gcd ( x , y ) \gcd(x, y) gcd(x,y) 表示 x , y x, y x,y 的最大公因数。)
x x x 的初始值为 n n n,你想通过若干次操作(也可不操作)将它变为 m m m。你想知道至少要多少次操作才能达成目标,或报告无解。
输入格式
本题有多组测试数据。
第一行输入一个正整数 T T T,表示测试数据组数。
对于每组测试数据:
第一行包含两个正整数 n , m n, m n,m。
输出格式
对于每组数据:
- 若无解,即 x x x 无论如何操作都不能变成 m m m,输出 − 1 -1 −1。
- 否则输出一行一个非负整数,表示最小的操作次数。
输入输出样例 #1
输入 #1
6
1 1
2 4
2 6
12 288
30 144000
114 5141919810
输出 #1
0
1
-1
2
3
-1
说明/提示
【样例解释】
对于第一组数据,无需进行任何操作,答案是 0 0 0。
对于第二组数据,可以选择 y = 6 y = 6 y=6,那么 x x x 会变成 2 × gcd ( 2 , 6 ) = 4 2 \times \gcd(2, 6) = 4 2×gcd(2,6)=4。
对于第三组数据,容易证明无论如何进行操作都不可能达成目标,所以输出 − 1 -1 −1。
对于第四组数据,可以:
- 选择 y = 16 y = 16 y=16,那么 x x x 会变成 12 × gcd ( 12 , 16 ) = 48 12 \times \gcd(12, 16) = 48 12×gcd(12,16)=48;
- 选择 y = 6 y = 6 y=6,那么 x x x 会变成 48 × gcd ( 48 , 6 ) = 288 48 \times \gcd(48, 6) = 288 48×gcd(48,6)=288。
【数据范围】
测试点编号 | n ≤ n \le n≤ | m ≤ m \le m≤ | 分值 |
---|---|---|---|
1 1 1 | 100 100 100 | 2 × 1 0 3 2 \times 10^3 2×103 | 21 21 21 |
2 2 2 | 2 2 2 | 1 0 18 10^{18} 1018 | 17 17 17 |
3 3 3 | 1 0 5 10^5 105 | 1 0 5 10^5 105 | 14 14 14 |
4 4 4 | 1 0 7 10^7 107 | 1 0 7 10^7 107 | 16 16 16 |
5 5 5 | 1 0 18 10^{18} 1018 | 1 0 18 10^{18} 1018 | 32 32 32 |
对于所有数据,满足 1 ≤ T ≤ 2 × 1 0 5 1 \le T \le 2 \times 10^5 1≤T≤2×105, 1 ≤ n ≤ m ≤ 1 0 18 1 \le n \le m \le 10^{18} 1≤n≤m≤1018。
C++实现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t;
ll n,m;
inline ll gcd(ll a,ll b)
{
while(b^=a^=b^=a%=b);
return a;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&m);
if(m%n)
{
puts("-1");
continue;
}
ll d=m/n,ans=0;
while(1)
{
ll g=gcd(n,d);
if(g==1) break;
d/=g,n*=g,ans++;
}
if(d>1) puts("-1");
else printf("%lld\n",ans);
}
return 0;
}
后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容