1006. 笨阶乘
我的思路1
- 举个🌰,对于 N = 10 N=10 N=10,结果是 12 12 12,计算顺序如下: 12 = 10 ∗ 9 / 8 + 7 − 6 ∗ 5 / 4 + 3 − 2 ∗ 1 12 = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1 12=10∗9/8+7−6∗5/4+3−2∗1
- 显然,可以四个一组,将数字1~10分为(10,9,8,7),(6,5,4,3),(2,1)三组。对于前面的个数为4的组,显然,可以直接运算。对于最后一组,特殊处理即可。
- 注意,任意两个组之间的运算符是减号。但是第一个组前面的符号应该是正号。
- +(10,9,8,7),-(6,5,4,3),-(2,1)
根据上述思路,可以写出AC代码:
class Solution {
public:
int clumsy(int N) {
int n = N / 4;
int ret = 0;
for (int i = 0; i < n; i ++){ // 对个数为4的组进行处理
int a = N - i * 4;
int b = N - i * 4 - 1;
int c = N - i * 4 - 2;
int d = N - i * 4 - 3;
int ans = a * b / c;
if (ret == 0){ // 第一次运算符号为正
ret += ans;
}else{ // 组之间的符号为负
ret -= ans;
}
ret += d;
}
int sign = n == 0 ? 1 : -1; // 有没有个数为4的组
int m = N % 4;
if (m == 3){
ret += sign * (3 * 2 / 1);
}else if (m == 2){
ret += sign * (2 * 1);
}else if (m == 1){
ret += sign * 1;
}
return ret;
}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.8 MB, 在所有 C++ 提交中击败了83.64%的用户
- 复杂度分析
- 时间复杂度: O ( N ) O(N) O(N)。一个for循环,来不及解释了。
- 空间复杂度: O ( 1 ) O(1) O(1)。只用到了可数个变量。
我的思路2
经验告诉我,这题可以 找规律 。
我们使用思路1的代码,我们使用Codeblocks打印前100项的结果:
#include<bits/stdc++.h>
using namespace std;
class Solution {
... // 思路1代码
};
int main(){
Solution s;
for (int i = 1; i <= 100; i ++){
cout << i << " " << s.clumsy(i) << " " << s.clumsy(i) - i << endl;
}
return 0;
}
console输出:
1 1 0
2 2 0
3 6 3
4 7 3
5 7 2
6 8 2
7 6 -1
8 9 1
9 11 2
10 12 2
11 10 -1
12 13 1
13 15 2
14 16 2
15 14 -1
16 17 1
17 19 2
18 20 2
19 18 -1
20 21 1
21 23 2
22 24 2
23 22 -1
24 25 1
25 27 2
26 28 2
27 26 -1
28 29 1
29 31 2
30 32 2
31 30 -1
32 33 1
33 35 2
34 36 2
35 34 -1
36 37 1
37 39 2
38 40 2
39 38 -1
40 41 1
41 43 2
42 44 2
43 42 -1
44 45 1
45 47 2
46 48 2
47 46 -1
48 49 1
49 51 2
50 52 2
51 50 -1
52 53 1
53 55 2
54 56 2
55 54 -1
56 57 1
57 59 2
58 60 2
59 58 -1
60 61 1
61 63 2
62 64 2
63 62 -1
64 65 1
65 67 2
66 68 2
67 66 -1
68 69 1
69 71 2
70 72 2
71 70 -1
72 73 1
73 75 2
74 76 2
75 74 -1
76 77 1
77 79 2
78 80 2
79 78 -1
80 81 1
81 83 2
82 84 2
83 82 -1
84 85 1
85 87 2
86 88 2
87 86 -1
88 89 1
89 91 2
90 92 2
91 90 -1
92 93 1
93 95 2
94 96 2
95 94 -1
96 97 1
97 99 2
98 100 2
99 98 -1
100 101 1
Process returned 0 (0x0) execution time : 0.377 s
Press any key to continue.
- 可以看到从第5项开始,
c
l
u
m
s
y
(
i
)
−
i
clumsy(i) - i
clumsy(i)−i开始以
2 2 -1 1
的规律循环。
因此,可以写出AC代码:
class Solution {
public:
int clumsy(int N) {
if (N == 1){
return 1;
}else if (N == 2){
return 2;
}else if (N == 3){
return 6;
}else if (N == 4){
return 7;
}
// 2 2 -1 1
int m = N % 4;
if (m == 1 || m == 2){
return N + 2;
}else if (m == 3){
return N - 1;
}else if (m == 0){
return N + 1;
}
return -1; // 不会执行到这里。
}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.9 MB, 在所有 C++ 提交中击败了51.51%的用户
-
复杂度分析:
- 时间复杂度: O ( 1 ) O(1) O(1).
- 空间复杂度: O ( 1 ) O(1) O(1).
-
证明:略。数学不好😣,我猜应该可以使用数学归纳法证明。
证明:思路2
在参考了其他人的证明后,发现证明其实并不难。
写出通用表达式:
f
(
n
)
=
n
(
n
−
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
4
)
(
n
−
5
)
n
−
6
+
(
n
−
7
)
−
…
f(n) = \frac {n(n-1)}{n-2} + (n-3) - \frac {(n-4)(n-5)}{n-6} + (n-7) - \ldots
f(n)=n−2n(n−1)+(n−3)−n−6(n−4)(n−5)+(n−7)−…
显然,我们是以4个为一组写出上述表达式的,因此,最后一项需要讨论。
如果n % 4 == 0
,显然,最后一项是
4
∗
3
/
2
+
1
4 * 3 / 2 + 1
4∗3/2+1,因此,
f
(
n
)
=
n
(
n
−
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
4
)
(
n
−
5
)
n
−
6
+
(
n
−
7
)
−
…
+
9
−
8
⋅
7
6
+
5
−
4
⋅
3
2
+
1
f(n) = \frac {n(n-1)}{n-2} + (n-3) - \frac {(n-4)(n-5)}{n-6} + (n-7) - \ldots + 9 - \frac {8\cdot7}{6} + 5 - \frac {4 \cdot 3} 2 + 1
f(n)=n−2n(n−1)+(n−3)−n−6(n−4)(n−5)+(n−7)−…+9−68⋅7+5−24⋅3+1
进行数学运算:
f
(
n
)
=
n
(
n
−
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
4
)
(
n
−
5
)
n
−
6
+
(
n
−
7
)
−
…
+
9
−
8
⋅
7
6
+
5
−
4
⋅
3
2
+
1
=
(
n
−
2
+
2
)
(
n
−
2
+
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
6
+
2
)
(
n
−
6
+
1
)
n
−
6
+
(
n
−
7
)
−
…
+
9
−
8
⋅
7
6
+
5
−
4
⋅
3
2
+
1
=
(
n
−
2
)
+
3
−
2
n
−
2
+
(
n
−
3
)
−
[
(
n
−
6
)
+
3
−
2
n
−
6
]
+
(
n
−
7
)
−
…
+
9
−
8
⋅
7
6
+
5
−
4
⋅
3
2
+
1
=
n
+
1
+
(
n
−
3
)
−
(
n
−
3
)
+
(
n
−
7
)
−
…
+
9
−
8
⋅
7
6
+
5
−
4
⋅
3
2
+
1
=
n
+
1
+
5
−
6
+
1
=
n
+
1
f(n) = \frac {n(n-1)}{n-2} + (n-3) - \frac {(n-4)(n-5)}{n-6} + (n-7) - \ldots + 9 - \frac {8\cdot7}{6} + 5 - \frac {4 \cdot 3} 2 + 1 \\ = \frac {(n - 2 + 2)(n - 2 + 1)} {n-2} + (n - 3) - \frac {(n - 6 + 2)(n - 6 + 1)}{n - 6} + (n - 7) - \ldots + 9 - \frac {8\cdot7}{6} + 5 - \frac {4 \cdot 3} 2 + 1 \\ = (n-2) + 3 - \frac {2}{n-2} + (n - 3) - [(n-6) + 3 - \frac {2}{n-6}] + (n - 7) - \ldots + 9 - \frac {8\cdot7}{6} + 5 - \frac {4 \cdot 3} 2 + 1 \\ = n + 1 + (n - 3) - (n-3) + (n - 7) - \ldots + 9 - \frac {8\cdot7}{6} + 5 - \frac {4 \cdot 3} 2 + 1 \\ = n + 1 + 5 - 6 + 1 \\= n + 1
f(n)=n−2n(n−1)+(n−3)−n−6(n−4)(n−5)+(n−7)−…+9−68⋅7+5−24⋅3+1=n−2(n−2+2)(n−2+1)+(n−3)−n−6(n−6+2)(n−6+1)+(n−7)−…+9−68⋅7+5−24⋅3+1=(n−2)+3−n−22+(n−3)−[(n−6)+3−n−62]+(n−7)−…+9−68⋅7+5−24⋅3+1=n+1+(n−3)−(n−3)+(n−7)−…+9−68⋅7+5−24⋅3+1=n+1+5−6+1=n+1
- 注意,最后的 5 − 4 ⋅ 3 2 5 - \frac{4 \cdot 3} 2 5−24⋅3不能被约去。
同理,如果n % 4 == 1
,显然,最后一项是
1
1
1,因此,此时,
f
(
n
)
=
n
(
n
−
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
4
)
(
n
−
5
)
n
−
6
+
(
n
−
7
)
−
…
−
9
⋅
8
7
+
6
−
5
⋅
4
3
+
2
−
1
=
n
+
1
+
2
−
1
=
n
+
2
f(n) = \frac {n(n-1)}{n-2} + (n-3) - \frac {(n-4)(n-5)}{n-6} + (n-7) - \ldots - \frac {9 \cdot 8} 7 + 6 - \frac {5 \cdot 4} 3 + 2 - 1 \\= n + 1 + 2 - 1 \\=n + 2
f(n)=n−2n(n−1)+(n−3)−n−6(n−4)(n−5)+(n−7)−…−79⋅8+6−35⋅4+2−1=n+1+2−1=n+2
如果n % 4 == 2
,最后一项是
2
∗
1
2*1
2∗1。此时,
f
(
n
)
=
n
(
n
−
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
4
)
(
n
−
5
)
n
−
6
+
(
n
−
7
)
−
…
−
7
+
6
⋅
5
4
+
3
−
2
⋅
1
=
n
+
1
+
3
−
2
=
n
+
2
f(n) = \frac {n(n-1)}{n-2} + (n-3) - \frac {(n-4)(n-5)}{n-6} + (n-7) - \ldots - 7 + \frac {6 \cdot 5} 4 + 3 - 2\cdot1 \\= n + 1 + 3 - 2 \\=n + 2
f(n)=n−2n(n−1)+(n−3)−n−6(n−4)(n−5)+(n−7)−…−7+46⋅5+3−2⋅1=n+1+3−2=n+2
如果n % 4 == 3
,最后一项是
3
∗
2
/
1
3*2/1
3∗2/1。此时,
f
(
n
)
=
n
(
n
−
1
)
n
−
2
+
(
n
−
3
)
−
(
n
−
4
)
(
n
−
5
)
n
−
6
+
(
n
−
7
)
−
…
−
8
+
7
⋅
6
5
+
4
−
3
⋅
2
1
=
n
+
1
+
4
−
6
=
n
−
1
f(n) = \frac {n(n-1)}{n-2} + (n-3) - \frac {(n-4)(n-5)}{n-6} + (n-7) - \ldots - 8 +\frac {7 \cdot 6} 5 + 4 - \frac{3\cdot2}{1} \\= n + 1 + 4 - 6 \\=n - 1
f(n)=n−2n(n−1)+(n−3)−n−6(n−4)(n−5)+(n−7)−…−8+57⋅6+4−13⋅2=n+1+4−6=n−1
2021.4.1 愚人节快乐