UVA11889 Benefit

题目大意

给定正整数 $a,c$,求使 $\operatorname{lcm}(a,b)=c$ 成立最小的 $b$,若没有满足条件的 $b$,输出 NO SOLUTION

思路分析

我们知道,

$$\operatorname{lcm}(a,b)=\prod p_i^{\max(k_{a_i},k_{b_i})}$$

将 $c$ 分解质因数,也可以得到

$$c=\prod p_i^{k_{c_i}}$$

要使 $\operatorname{lcm}(a,b)=c$,代入一下得到

$$\prod p_i^{k_{c_i}}=\prod p_i^{\max(k_{a_i},k_{b_i})}$$

即对于每一个质数 $p_i$,有

$$k_{c_i}=\max(k_{a_i},k_{b_i})$$

因为我们已经知道 $k_{c_i}$ 和 $k_{a_i}$,只要求出满足条件的最小的 $k_{b_i}$ 就可以了。记住“最小的”这三个字。

我们分类讨论一下:

  • 当 $k_{c_i} < k_{a_i}$ 时:

    显然 $\max(k_{a_i},k_{b_i}) > k_{c_i}$。

    输出 NO SOLUTION

  • 当 $k_{c_i} > k_{a_i}$ 时:

    要想使其成立,必须使 $k_{b_i}=k_{c_i}$。

  • 当 $k_{c_i} = k_{a_i}$ 时:

    因为 $k_{b_i}$ 是非负整数,所以我们将 $k_{b_i}$ 取最小值 $0$ 即可。

实际上,分解质因数我们可以先把每个数的最小质因数提前筛出来,然后 $O(\log n)$ 求解就可以了。因为最后求 $b$ 的循环里面套了一个快速幂,所以总时间复杂度 $O(t\log^2n)$,足以通过此题。

本题坑点

在最后处理 $b$ 的时候一定要记得把没有在 $a$ 的质因数里出现但是在 $c$ 的质因数里出现的数乘上去。

完整代码

#include <bits/stdc++.h>
#define int long long

using namespace std;

typedef map<int, int>::iterator iter;

const int maxn = 1e5 + 1;
const int maxm = 1e7 + 1;

int prime[maxm], cnt;
bool book[maxm];
int fc[maxm];

void sieve()  {
    for (int i = 2; i < maxm; i++) {
        if (!book[i]) {
            prime[++cnt] = i;
            fc[i] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < maxm; j++) {
            book[i * prime[j]] = true;
            fc[i * prime[j]] = prime[j];
            if (i % prime[j] == 0) break;
        }
    }
}

int power(int base, int freq) {
    int ans = 1, tmp = base;
    while (freq > 0) {
        if (freq % 2 == 1) ans = ans * tmp;
        freq /= 2;
        tmp = tmp * tmp;
    }
    return ans;
}

int t, a, c, b = 1;
map<int, int> sa;
map<int, int> sc;

signed main() {
    cin >> t;
    while (t--) {
        sa.clear();
        sc.clear();
        bool fl = true;
        cin >> a >> c;
        b = 1;
        while (a != 1) {
            if (sa.count(fc[a])) sa[fc[a]]++;
            else sa[fc[a]] = 1;
            a /= fc[a];
        }
        while (c != 1) {
            if (sc.count(fc[c])) sc[fc[c]]++;
            else sc[fc[c]] = 1;
            c /= fc[c];
        } 
        for (iter i = sa.begin(); i != sa.end(); i++) {
            if (!sc.count(i->first) || sc[i->first] < i->second) {
                fl = false;
                break;
            } 
            if (sc[i->first] == i->second) {
                sc[i->first] = 0;
                continue;
            }
            b *= power(i->first, sc[i->first]);
            sc[i->first] = 0;
        }
        for (iter i = sc.begin(); i != sc.end(); i++) {
            b *= power(i->first, i->second);
        }
        if (!fl) {
            cout << "NO SOLUTION" << endl;
            continue;
        }
        cout << b << endl;
    }
    return 0;
}
posted @   TernaKagiri  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示