专栏文章

CF2114F

CF2114F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minp2p7e
此快照首次捕获于
2025/12/02 06:02
3 个月前
此快照最后确认于
2025/12/02 06:02
3 个月前
查看原文

题解

注意到最好的方案是将 aa 通过操作转化为 gcd(a,b)\gcd(a,b) 再将其转化为 bb
证:若转化到低于 gcd(a,b)\gcd(a,b) 的数,下一步最优肯定要转化到 bb 的因数。由于有 kk 的限制,所以在合法方案下,在 gcd(a,b)\gcd(a,b) 上可以一步转化到的一个数 xx,在低于 gcd(a,b)\gcd(a,b) 上需要至少一次操作转化到 xx。因此从 gcd(a,b)\gcd(a,b) 转化不劣。
然后设 x=agcd(a,b)x=\frac{a}{\gcd(a,b)}y=bgcd(a,b)y=\frac{b}{\gcd(a,b)},此时 gcd(x,y)=1\gcd(x,y)=1,问题转化为将 xx 变为 11 再变为 yy 的最小操作次数。
可以看作将 xx 除到 11 加上将 yy 除到 11 的操作次数,前提为除数小于等于 kk
发现如果 xxyy 中有任意一个,它的最大质因数大于 kk,则无解。
其余情况皆有解,用记忆化搜索即可。
memset 炸了,考试慎用 memset

代码

CPP
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
int _;
ll x,y,k;
ll f[N];
inline ll dfs(ll x) {
	if(x==1) return 0;
	if(x<=k) return 1;
	if(f[x]!=-1) return f[x];
	for(int i=k;i>1;i--) {
		if(x%i==0) {
			ll nxt=dfs(x/i);
			if(nxt==-1) continue;
			if(f[x]==-1) f[x]=nxt+1ll;
			else f[x]=min(f[x],nxt+1ll);
		}
	}
	return f[x];
}
inline ll gcd(ll a,ll b) {
	if(!b) return a;
	return gcd(b,a%b);
}
int main() {
	scanf("%d",&_);
	while(_--) {
		scanf("%lld%lld%lld",&x,&y,&k);
		ll g=gcd(x,y);
		ll a=x/g,b=y/g;
		for(int i=1;i<=max(a,b);i++) f[i]=-1;
		if(dfs(a)==-1||dfs(b)==-1) puts("-1");
		else printf("%lld\n",dfs(a)+dfs(b));
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...