CF221A Little Elephant and Function 题解
Content
小象有一个序列 \(a_1,a_2,a_3,...,a_n\) (其中 \(a_i=i\))和一个递归函数 \(f(x)\)。\(f(x)\) 的操作如下:
- 初始时,\(x=n\)。
- 如果 \(x=1\),退出函数;否则,交换 \(a_{x-1},a_x\),并且递归至 \(f(x-1)\)。
现在,小象想知道执行完函数以后序列的结果。
数据范围:\(1\leqslant n\leqslant 1000\)。
Solution
这道题目由于 \(n\) 很小,我们可以考虑多种做法。
Sol.1 递归暴力法
我们可以直接模拟出像题面中的 \(f(x)\) 那样的递归函数,并且直接按照题面所要求的操作模拟,最后输出结果。
Sol.2 非递归暴力法
我们可以发现,它无疑就是从 \(n\) 循环到 \(2\),每次就交换罢了,因此,我们可以不需要递归,直接用一个循环来一次一次交换就好。
Sol.3 更优的解法
我们还可以考虑出更简单的做法。
我们可以发现,所有的操作完了以后,原来在序列中排在最后的 \(n\) 直接调到了首位,其他的整体往后移了一位。
像这样:
1 2 3 4 5 6 7 8 9 10
操作1:
1 2 3 4 5 6 7 8 10 9
操作2:
1 2 3 4 5 6 7 10 8 9
操作3:
1 2 3 4 5 6 10 7 8 9
操作4:
1 2 3 4 5 10 6 7 8 9
操作5:
1 2 3 4 10 5 6 7 8 9
操作6:
1 2 3 10 4 5 6 7 8 9
操作7:
1 2 10 3 4 5 6 7 8 9
操作8:
1 10 2 3 4 5 6 7 8 9
操作9:
10 1 2 3 4 5 6 7 8 9
结束。
所以,操作完之后的序列就是 \(n,1,2,3,...,n-1\)。
Code
1
#include <cstdio>
#include <algorithm>
using namespace std;
int n, a[1007];
void f(int x) {
if(x == 1) return;
swap(a[x - 1], a[x]);
f(x - 1);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) a[i] = i;
f(n);
for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
}
2
#include <cstdio>
#include <algorithm>
using namespace std;
int n, a[1007];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) a[i] = i;
for(int i = n; i >= 2; --i) swap(a[i - 1], a[i]);
for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
}
3
#include <cstdio>
#include <algorithm>
using namespace std;
int n, a[1007];
int main() {
scanf("%d", &n);
printf("%d", n);
for(int i = 1; i < n; ++i) printf(" %d", i);
}