# Leetcode:No.650 2 Keys Keyboard

Initially on a notepad only one character 'A' is present. You can perform two operations on this notepad for >each step:

Copy All: You can copy all the characters present on the notepad (partial copy is not allowed).
Paste: You can paste the characters which are copied last time.
Given a number n. You have to get exactly n 'A' on the notepad by performing the minimum number of steps permitted. Output the minimum number of steps to get n 'A'.

Example 1:
Input: 3
Output: 3
Explanation:
Intitally, we have one character 'A'.
In step 1, we use Copy All operation.
In step 2, we use Paste operation to get 'AA'.
In step 3, we use Paste operation to get 'AAA'.
Note:
The n will be in the range [1, 1000].

DP第一步要确定含义，一般来说都是直指问题，也就是说设dp[i]是得到i个A所需要的最少步数。

dp[k*i]=dp[i] + k ，其中k是大于1的正整数，copy1次paste k-1次。

``````dp[i] = dp[j] + i/j
``````

``````# Time: O(n)
# Space: O(n)
class Solution:
def dp(self, n):
dp = [_ for _ in xrange(n + 1)]
dp[1] = 0
for i in xrange(1, n + 1):
for j in reversed(xrange(1, i / 2 + 1)):
if i % j == 0:
dp[i] = dp[j] + i / j
break
return dp[-1]
``````

``````    public int minSteps(int n) {
int s = 0;
for (int d = 2; d <= n; d++) {
while (n % d == 0) {
s += d;
n /= d;
}
}
return s;
}
``````

d代表divisor，s代表step。因为整除关系是不分先后顺序的，所以d从2开始先把n所有的2因数扫出来，然后递增循环。可以想象成从最后逆推的过程，只不过采用贪婪算法，每次取最小因数，此时被paste的A的数量最多。

`d * d <= n`

``````    public int minSteps(int n) {
int s = 0;
for (int d = 2; d * d <= n; d++) {
while (n % d == 0) {
s += d;
n /= d;
}
}
return s + (n == 1 ? 0 : n);
}
``````

``````public int minSteps(int n) {
// list of primes that are not greater than SQRT(n) - in this case, n = 1,000, SQRT(n) = 31.6
int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
int ans = 0;
for (int p : primes) {
while (n % p == 0) {
ans += p;
n /= p;
}
}
return ans + (n == 1 ? 0 : n);
}
``````