专栏文章
CF2114F Small Operations 题解
CF2114F题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min3hd6v
- 此快照首次捕获于
- 2025/12/01 19:57 3 个月前
- 此快照最后确认于
- 2025/12/01 19:57 3 个月前
思路
令 ,,。易知最少操作次数一定是把 先除到 ,再乘到 。可以将除 转化为乘 再取倒数。所以问题就变成了 通过一直乘若干个 的整数 ,使其变为 , 的最小操作次数。
直接用 DP 解决。设 代表从 到 的最小操作次数。则:
所以答案就为 。如果 ,则无解。因为需要 中每一个数的所有因数,所以用 的方法解决。我们会发现,不用枚举 ,只用枚举 的所有因数即可。
令 时。间复杂度 ,其中 为 的因数个数,在 时 。可以通过。
代码
CPP#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5, inf = 1e9;
int t, x, y, k;
vector<int> fact[N];
int dp[N];
void init()
{
for (int i = 1; i < N; i++)
for (int j = i; j < N; j += i)
fact[j].push_back(i);
for (int i = 1; i < N; i++) dp[i] = inf;
}
int calc(int n)
{
dp[1] = 0;
for (int i : fact[n])
for (int j : fact[i])
if (j <= k) dp[i] = min(dp[i], dp[i / j] + 1);
int now = dp[n];
for (int i : fact[n]) dp[i] = inf;
return now;
}
void solve()
{
scanf("%d%d%d", &x, &y, &k);
int d = __gcd(x, y);
int a = x / d, b = y / d;
int res = calc(a) + calc(b);
if (res >= inf) printf("-1\n");
else printf("%d\n", res);
}
int main()
{
init();
scanf("%d", &t);
while (t--) solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...