F. Small Operations

F. Small Operations

Given an integer $x$ and an integer $k$. In one operation, you can perform one of two actions:

  • choose an integer $1 \le a \le k$ and assign $x = x \cdot a$;
  • choose an integer $1 \le a \le k$ and assign $x = \frac{x}{a}$, where the value of $\frac{x}{a}$ must be an integer.

Find the minimum number of operations required to make the number $x$ equal to $y$, or determine that it is impossible.

Input

The first line of the input contains one integer $t$ ($1 \le t \le 10^4$) — the number of test cases.

The only line of each test case contains three integers $x$, $y$ and $k$ ($1 \le x, y, k \le 10^6$).

It is guaranteed that the sum of $x$ and the sum of $y$ across all test cases does not exceed $10^8$.

Output

For each test case, output $-1$ if it is impossible to achieve $x=y$ using the given operations, and the minimum number of required operations otherwise.

Example

Input

8
4 6 3
4 5 3
4 6 2
10 45 3
780 23 42
11 270 23
1 982800 13
1 6 2

Output

2
-1
-1
3
3
3
6
-1

 

解题思路

  令 $d = \gcd(x,y)$,有 $x = \frac{x}{d} \cdot d$,其中 $\frac{x}{d}$ 是 $y$ 中不存在的因子,需要通过操作 $2$ 从 $x$ 中除去。又因为 $y = \frac{y}{d} \cdot d$,还需要通过操作 $1$ 对除剩的 $d$ 乘上 $\frac{y}{d}$ 将其变成 $y$。显然两种操作是独立的,对于操作 $1$ 我们希望用最少的次数凑出 $\frac{y}{d}$。对于操作 $2$ 则希望用最少的次数凑出 $\frac{x}{d}$。

  上面两种操作都可以归为一个问题:凑出某个值 $v$ 的最少次数是多少。赛时想到的做法是先将 $v$ 进行质因数分解 $v = p_1^{\alpha_1} p_2^{\alpha_2} \cdots p_k^{\alpha_k}$,由于 $\alpha_1 + \alpha_2 + \cdots + \alpha_k \leq \log{X} < 20$,因此很容易想到状压 dp。

  定义 $f(s)$ 表示凑出二进制状态 $s$ 所表示的质因子的乘积的最少次数,根据最后一次操作凑出的乘积进行转移,即枚举 $s$ 的所有非空子集进行状态转移。有状态转移方程 $f(s) = \min\limits_{t \subseteq s \text{ and } f(t) \leq k}\left\{ f(t) \right\} + 1$,其中 $f(t)$ 是二进制状态 $t$ 表示的质因子的乘积。整个 dp 的复杂度是 $O\left(3^{\log{v}}\right)$,过不了。

  可以发现,每次操作实际上是凑出 $v$ 的一个约数,包括上述 dp 每次转移的状态 $t$ 对应质因子的乘积也是 $v$ 的约数。所以我们能不能不考虑质因子的组合,而是每次通过一个约数进行转移?

  重新定义 $f(i)$ 表示凑出值 $i$ 所需的最少次数,根据最后一次操作凑出的 $i$ 的约数进行转移,状态转移方程为 $f(i) = \min\limits_{d \leq k \mid i}\left\{ f\left(\frac{i}{d}\right) \right\} + 1$。这样时间复杂度就降到了 $O(v \log{v})$ 了。不过如果直接从 $1$ 到 $v$ 去枚举 $i$ 进行转移还是会超时,博主不知道为什么,麻烦知道的大佬在评论区留言 qwq。优化的方法也很简单,如果 $i \nmid v$ 显然状态 $f(i)$ 是不存在的,因为我们每次都凑出 $v$ 的约数,所以之前累乘的结果也是 $v$ 的约数。因此我们只需从小到大枚举 $i \mid v$ 的 $i$ 进行转移即可。 

  AC 代码如下,时间复杂度为 $O(X \log{X} + Y \log{Y})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e6 + 5, INF = 0x3f3f3f3f;

int x, y, k;
vector<int> ds[N];
int f[N];

void init() {
    for (int i = 2; i < N; i++) {
        for (int j = i; j < N; j += i) {
            ds[j].push_back(i);
        }
    }
}

int get(int n) {
    for (auto &i : ds[n]) {
        f[i] = INF;
        for (auto &j : ds[i]) {
            if (j > k) break;
            f[i] = min(f[i], f[i / j] + 1);
        }
    }
    return f[n];
}

void solve() {
    cin >> x >> y >> k;
    int d = __gcd(x, y);
    int ret = get(x / d) + get(y / d);
    cout << (ret < INF ? ret : -1) << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round #1027 (Div. 3) Editorial:https://codeforces.com/blog/entry/143268

posted @ 2025-05-27 21:41  onlyblues  阅读(63)  评论(0)    收藏  举报
Web Analytics