[M数学] lc650. 只有两个键的键盘(dp+思维+质因数)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M数学] lc650. 只有两个键的键盘(dp+思维+质因数)相关的知识,希望对你有一定的参考价值。
1. 题目来源
2. 题目解析
十分好的一道题目啊。数学的 O ( n ) O(\\sqrt n) O(n) 解法,和 dp 的 O ( n ) O(n) O(n) 解法都很不错。
方法一:数学+质因数分解
- 考虑,
n
=
x
1
∗
x
2
∗
.
.
.
∗
x
k
n=x_1*x_2*...*x_k
n=x1∗x2∗...∗xk,我们可视为
x
1
x_1
x1 是先复制一次,然后粘贴
x
1
−
1
x_1-1
x1−1 次,那么现在的总长度就是:原有的一个
A
加上 x 1 − 1 x_1-1 x1−1 个A
,也就是共x_1
个A
,即x_1
即为总长度。 - 而针对
x_2
,我们也可视为是先将现有总长度复制一次,然后在后面粘贴 x 2 − 1 x_2-1 x2−1次,那么总长度就是 x 1 + x 1 ( x 2 − 1 ) x_1+x_1(x_2-1) x1+x1(x2−1) 即为 x 1 ∗ x 2 x_1*x_2 x1∗x2。 - 同理可得, n = x 1 ∗ x 2 ∗ . . . ∗ x k n=x_1*x_2*...*x_k n=x1∗x2∗...∗xk 只要将 n n n 分解为 x i ≥ 2 x_i \\ge 2 xi≥2正整数的乘积,就能一一对应一种方案。 乘以数字 1 是没有意义的。而数字之和就是操作次数。
- 再考虑,当乘数中有合数出现时,合数一定可以因式分解。即 x = p ∗ q , x ≥ 2 , p , q > 1 x=p*q, x\\ge2,p,q\\gt1 x=p∗q,x≥2,p,q>1,我们仅需证明 p + q ≤ x {p+q}\\le x p+q≤x 即可证明任意合数都可以进行分解,那么最后必然是所有的质数的乘积构成 n n n。即答案(操作次数)即为 n n n 的所有质因子分解式的和。
- 考虑, ( p − 1 ) ∗ ( q − 1 ) > 1 (p-1)*(q-1)>1 (p−1)∗(q−1)>1,因为 p , q > 1 p,q>1 p,q>1,那么 ( p − 1 ) ∗ ( q − 1 ) = p ∗ q − p − q + 1 = x − p − q + 1 > 1 (p-1)*(q-1)=p*q-p-q+1=x-p-q+1>1 (p−1)∗(q−1)=p∗q−p−q+1=x−p−q+1>1,那么 x > p + q x\\gt p + q x>p+q 恒成立。
- 这就说明了 n = x 1 ∗ x 2 ∗ . . . ∗ x k n=x_1*x_2*...*x_k n=x1∗x2∗...∗xk 不存在合数,即全为质数。那么由整数唯一分解定理可得 n n n 有唯一质因数分解式,累加和即为答案。
方法二:dp
- 贪心怕是不行,那就 dp 呗。
- 状态定义:
f[i]
表示得到i
个字符A
所需的最小操作次数。初始化f[1]=0
。答案f[n]
。 - 状态转移:每次考虑最后一个位置是从哪转移过来的。 可以明确的是,多次 copy 情况下,我们只需要枚举
i
的所有约数j
即可。即f[i]=f[j]+i/j
意味着i/j
次中,经历一次复制f[j]
个,i/j -1
次拷贝到达状态i
。和数学解法的思路大致一样。同理,也可以f[i]=f[i/j]+j
,经历一次复制f[i/j]
个,拷贝j-1
次到达状态i
。 - 状态转移剪枝:
- 在枚举
i
的约数时,显然只需要枚举到根号i
- 也可以枚举
i
的时候只考虑n%i==0
的所有的i
情况即可。但是这个想法比较抽象,不推荐。也懒得去想证明了。
- 在枚举
当然这种选不选问题,可以 dfs
,但没必要。
- 时间复杂度: O ( n ) O(\\sqrt n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
dp
class Solution {
public:
int minSteps(int n) {
vector<int> f(n + 1, 1e9);
f[1] = 0;
for (int i = 2; i <= n; i ++ ) {
// if (n % i == 0) // 加上优化效率,剪枝。
for (int j = 1; j <= i / j; j ++ ) {
if (i % j == 0) {
f[i] = min(f[i], f[j] + i / j);
f[i] = min(f[i], f[i / j] + j);
}
}
}
return f[n];
}
};
数学
class Solution {
public:
int minSteps(int n) {
int res = 0;
for (int i = 2; i <= n / i; i ++ ) {
if (n % i == 0) {
int t = 0;
while (n % i == 0) n /= i, t ++ ;
res += i * t;
}
}
if (n > 1) res += n;
return res;
}
};
以上是关于[M数学] lc650. 只有两个键的键盘(dp+思维+质因数)的主要内容,如果未能解决你的问题,请参考以下文章
[M数学] lc650. 只有两个键的键盘(dp+思维+质因数)