专栏文章

题解:CF2114F Small Operations

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

文章操作

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

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

题目描述

给你两个正整数 x,kx,k。进行以下两种变换之一称为一次操作:
  • 选择一个满足 1ak1 \le a \le k 的正整数 aa,使 xx 变为 xax\cdot a
  • 选择一个满足 1ak1 \le a \le k 的正整数 aa,使 xx 变为 xa\frac{x}{a},要求操作完后 xx 值是整数。
你需要找出使 xx 变为给定正整数 yy 的最小操作次数,或判断无解。

Sol

考虑先将 xx 变为 gcd(x,y)\gcd(x,y) 再将 gcd(x,y)\gcd(x,y) 变为 yy。显然这样操作所需的次数最少。
先将 xgcd(x,y)\frac{x}{\gcd(x,y)}ygcd(x,y)\frac{y}{\gcd(x,y)} 因数分解,再用 dp 将其凑起来就行。
dpidp_i 为当前因数的乘积为 ii 是所需的最小操作次数,dpdp 的过程就用记忆化搜索就行了。
dpi=max(dpi,dpid(i)+1)\large dp_i=\max (dp_i,dp_\frac{i}{d(i)} +1)
其中 d(i)d(i) 为小于 kkii 的因数。

Code

CPP
#include<bits/stdc++.h>
using namespace std;
int dp[1000005];
bool check(int x,int k){
	for (int i=2;i*i<=x&&i<=k;i++) while (x%i==0) x/=i;
	return (x<=k);
}

int dfs(int x,int k){
	if(x==1) return 0;
	if(dp[x]) return dp[x];
	if(x<=k){
		dp[x]=1;
		return 1;
	}
	dp[x]=1e9;
	for(int i=k;i>1;i--) if(x%i==0) dp[x]=min(dp[x],dfs(x/i,k)+1);
	return dp[x];
}



int main(){
	int T;
	cin>>T;
	while(T--){
		memset(dp,0,sizeof dp);
		int a,b,k,ans=0;
		cin>>a>>b>>k;
		int fk=__gcd(a,b);
		a=a/fk,b=b/fk;
		if(!check(a,k) || !check(b,k)){
			cout<<-1<<endl;
			continue; 
		}
		cout<<dfs(a,k)+dfs(b,k)<<endl;
	}
} 

评论

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

正在加载评论...