1=N
[题目链接](https://www.nowcoder.com/practice/31469f8503c24914acd5c0290ad4dfbb)
思路
先来理解题意。初始 ,每次操作可以选一个
,花费
的代价把
变成
。目标是让
,问最小总代价。
换句话说,我们要把 写成若干个
的整数的乘积
,使得
最小。
那什么样的分解方式代价最小呢?
假如某个 是合数,比如
(
),那把它拆成两步
和
,代价从
变成
。由于
,显然
(等号在
时成立)。所以把合数拆开,代价不会变大。
这就意味着:最优方案一定是把 分解成质因数的乘积,每一步选一个质因子作为
。最终答案就是
的所有质因数之和(含重复)。
拿样例验证一下:,代价
,正确。
特别地, 时不需要任何操作,代价为
。
做质因数分解只需要从 开始试除,每次能整除就累加该因子并除掉,直到
。如果最后剩余的
,说明它本身是一个质因子,也要加上。
代码
#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
int cost = 0;
for(int p = 2; p * p <= n; p++){
while(n % p == 0){
cost += p;
n /= p;
}
}
if(n > 1) cost += n;
cout << cost << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int cost = 0;
for (int p = 2; p * p <= n; p++) {
while (n % p == 0) {
cost += p;
n /= p;
}
}
if (n > 1) cost += n;
System.out.println(cost);
}
}
n = int(input())
cost = 0
p = 2
while p * p <= n:
while n % p == 0:
cost += p
n //= p
p += 1
if n > 1:
cost += n
print(cost)
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
rl.on('line', (line) => {
let n = parseInt(line.trim());
let cost = 0;
for (let p = 2; p * p <= n; p++) {
while (n % p === 0) {
cost += p;
n = Math.floor(n / p);
}
}
if (n > 1) cost += n;
console.log(cost);
rl.close();
});
复杂度分析
- 时间复杂度:
。试除法最多枚举到
,内层 while 循环的总次数不超过
。
- 空间复杂度:
。只用了常数个变量。

京公网安备 11010502036488号