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);
}
posted @ 2021-12-21 21:01  Eason_AC  阅读(27)  评论(0)    收藏  举报