首页 > 其他分享 >题解 UVA10791

题解 UVA10791

时间:2022-08-26 21:57:02浏览次数:152  
标签:UVA10791 int 题解 质数 最小 times 公倍数 分解

前言:

数学符号约定:

  1. \(p\) :任意一个质数

  2. \(n\) 或 \(m\):任意一个正整数

  3. \(a_i\):唯一分解时质数的指数

  4. \(A\):集合

若无特殊说明,本篇题解的数学符号将会严格按照上述符号进行编写。

题目描述:

给定一个数 \(n\),求出至少两个数,使得他们的最小公倍数为 \(n\),且相加最小。

题目分析:

首先,我们浅浅的思考一下,很容易得出一个结论,多个数的最小公倍数其实就是他们唯一分解后每个质数的最小幂的乘积。打个比方,比如对于 \(12\) 和 \(30\) 来说,对他们分别进行唯一分解后,得出的结果分别是:

\[12=2^2\times 3^1 \]

\[30=3^2 \times 5^1 \]

所以他们的最小公倍数就是:

\[\operatorname{lcm}(12,30)=2^2 \times 3^1 \times 5^1 = 60 \]

根据这个结论,我们可以反向思考,对一个数来说,其唯一分解出的每个质数幂所组成的集合中所有元素的最小公倍数必定是这个数,举个例子,对于 \(1890\) 来说,对其进行唯一分解后得出的结果为:

\[1890 = 2^1 \times 3^3 \times 5^1 \times 7^1 \]

所以,分解出的每个质数幂所组成的集合 \(A\) 为:

\[A=\{2^1,3^3,5^1,7^1\} \]

由此,我们不难看出,集合 \(A\) 中的所有元素的最小公倍数即为:

\[\operatorname{lcm}(A)=\operatorname{lcm}(2^1,3^3,5^1,7^1)=2^1 \times 3^3 \times 5^1 \times 7^1 =1890 \]

现在,我们再思考另一个问题,对于多个大于 \(1\) 且两两不同的正整数来说,如何在他们的乘积不变的情况下相加最小。

首先,对于两个正整数 \(n\) 和 \(m\) (\(n\) 和 \(m\) 都大于 \(1\),且保证 \(n\) 和 \(m\) 不同)来说,我们可以十分轻易地看出来,\(n \times m\) 一定是大于 \(n + m\) 的。证明如下:

\[\begin{array}{r} (n-1)\times(m-1) > 1\\ n \times m - n - m + 1 > 1\\ n \times m - n - m >0\\ n \times m > n+m \end{array} \]

所以,对于任意一个非质数幂合数 \(n\),若有多个整数的最小公倍数为它,则这些整数的和的最小值就应当为合数 \(n\) 唯一分解后的质数幂的和。

那么对于质数幂来说,就不适用上面的结论了,因为质数幂的唯一分解还是其本身,不满足题目条件“至少两个数”,解决方法也十分简单,如果一个数为质数幂,那么它的结果就应当是其本身加 \(1\)。

那么,问题又来了,我们需不需要判断他是不是质数幂呢,答案显然是不需要,我们只需要在唯一分解时,判断这个数是否只由一种质数组成即可。

代码实现:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int ResolveNumber(int n) { //唯一分解并求得答案。 
    int fin = sqrt(n); 
    int kinds = 0; //质数的种类个数。 
    int answer = 0; 

    for (int i = 2; i <= fin; i++) {
        int power = 0;

        if (n % i == 0) {
            kinds++;
            power = 1;
        }

        while (n % i == 0) {
            n /= i;
            power *= i;
        }

        answer += power;
    }

    if (n > 1) {
        answer += n;
        kinds++;
    }

    if (kinds == 1) //如果只有一种质数,则证明其为质数或质数幂,那我们就把结果加 1。 
        ++answer;

    return answer;
}
signed main() {
    int cnt = 0;

    while (1) {
        int n;
        cin >> n;

        if (n == 0) 
            break;

        if (n == 1) //特判一下 1。 
            printf("Case %lld: 2\n", ++cnt);
        else
            printf("Case %lld: %lld\n", ++cnt, ResolveNumber(n));
    }

    return 0;
}

标签:UVA10791,int,题解,质数,最小,times,公倍数,分解
From: https://www.cnblogs.com/larry76/p/16629368.html

相关文章

  • 20220823 模拟赛题解
    T1文件压缩DecriptionlinkSolution可以根据\(S'\)和\(p\)求出第一个字符,然后把\(S'\)sort一遍后得到字符串\(T\),那么我们就可以求出每一个字符的前驱和后继,所......
  • LeetCode 链表的中间结点算法题解 All In One
    LeetCode链表的中间结点算法题解AllInOnejs/ts实现重排链表链表的中间结点原理图解//快慢指针functionmiddleNode(head:ListNode|null):ListNode|n......
  • k8s问题解决
    问题1:问题描述:k8s中Terminating状态pod不能删除[root@master~]#kubectlgetpods-nmsNAMEREADYSTATUSRESTARTSAGEportal-78......
  • Unable to create an object of type 'DbContext'问题解决,网上搜来的没一个对的。
    用了很久的EFCore了,第一次遇到这个问题,觉得很奇怪,baidu了一下,都是要提供设计时工厂的答案。很明显这个做法是有问题的,都是DI的年代了,你的DbContext又不是动态生产了一堆......
  • P1399 [NOI2013] 快餐店 题解
    题目大意求一棵基环树的重心。即一个点,使得树上到其距离最长的点到其的距离最短。注意,这个点不一定是一个节点,可以在树上的任意位置。输出树上到其距离最长的点到其的距离......
  • P8443 题解
    前言题目传送门!更好的阅读体验?普及组月赛第一题。别的题解语言有点高深,我补篇题解。思路显然,\(\lfloor\dfrac{l}{x}\rfloor,\lfloor\dfrac{l+1}{x}\rfloor,\cdot......
  • P8431 题解
    前言题目传送门!更好的阅读体验?这题题解都写得特别复杂,蒟蒻看不懂。因此,我补一篇简单的贪心题解。思路题目等同于求最小的\(p\)使得\(f(p)>n\),则\((p-1)\)就是答......
  • P7535 题解
    前言题目传送门!更好的阅读体验?比赛时考到了这一题,于是写一篇题解纪念一下。思路设\(dp_{i,j}\)表示前\(i\)张钞票分给两人,两人差尽可能接近\(j\)的情况下,获得......
  • CF1066C 题解
    前言题目传送门!更好的阅读体验?本题是简单的双端队列练手题。思路题意大致如下:执行双端队列push_front()操作。执行双端队列push_back()操作。查询\(\min\{m......
  • SP733 题解
    前言题目传送门!更好的阅读体验?校内比赛题。赶紧补篇题解。思路经典的二分加搜索。由于\(h_{i,j}\)范围很小,考虑二分答案。二分答案的范围应该是\([0,110]\)。......