题目描述
花果山近期举办了一场编程测试,总计有
n
n 只猴子参加了测试并提交了答案。悟空正准备修改试卷时突然收到了蟠桃会的邀请,机智的悟空想到了一个好办法,让猴子们自己根据答案修改试卷。为了防止作弊,悟空规定每只猴子都不能修改自己的试卷,问修改试卷的方式一共有多少种方式。
输入格式
参加测试猴子只数
n,保证
n
≤
20
n≤20。
输出格式
一个整数,代表有多少种情况。
输入输出样例
输入
2
输出
1
输入
3
输出
2
说明/提示
对于
100
%
100% 的数据,
1
≤
n
≤
20
1≤n≤20。
来咯:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> dp(n + 1);
dp[0] = 1;
dp[1] = 0;
for (int i = 2; i <= n; i++) {
dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]);
}
cout << dp[n] << endl;
return 0;
}
参考GPT:这道题目需要求解的是有多少种修改试卷的方式,满足每只猴子都不能修改自己的试卷。这是一个比较典型的排列组合问题,可以用递归的方式求解。
我们可以将猴子编号为 1 到 n,假设当前要考虑第 i 只猴子应该修改哪一份试卷。由于该猴子不能修改自己的试卷,因此有 n-1 种选择,即该猴子可以选择修改编号为 1 到 n-1 的任意一份试卷。
假设我们已经确定了第 i 只猴子要修改第 j 只猴子的试卷,那么问题就转化成了在剩下的 n-2 只猴子中,如何让它们修改试卷,而且每只猴子都不能修改自己的试卷。这是一个子问题,可以通过递归来求解。
最终,我们将所有子问题的解相加即可得到最终的答案。
下面是用 C++ 实现的代码:
#include <iostream>
#include <vector>
using namespace std;
int count(int n, vector<int>& used) {
if (n == used.size()) {
return 1;
}
int cnt = 0;
for (int i = 0; i < used.size(); i++) {
if (used[i] == 0 && i != n) {
used[i] = 1;
cnt += count(n+1, used);
used[i] = 0;
}
}
return cnt;
}
int main() {
int n;
cin >> n;
vector<int> used(n, 0);
cout << count(0, used) << endl;
return 0;
}
参考GPT和自己的思路:
这个问题是一个排列组合问题,具体的做法是将 n 个猴子看作 n 个球,需要将这些球分成 n 组,每组里有一个球留空代表这个猴子不能修改自己的试卷。因此,将 n 个猴子排成一队,有 n 种选择第一个球留空,第一个球留空后,剩下的猴子就变成了一个规模为 n - 1 的子问题,所以总方案数为 n-1 的阶乘。
因此,C++ 代码应该为:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int cnt = 1;
for(int i = 2; i < n; i++)
{
cnt *= i;
}
cout << cnt << endl;
return 0;
}
根据题目描述,猴子们要互相交换试卷,且每只猴子都不能修改自己的试卷,因此可以考虑使用递归来解决问题。
假设现在需要将第i只猴子和第j只猴子的试卷交换,如果i=j,则这种情况不合法,直接返回0;否则,可以交换他们的试卷,然后递归处理剩下的猴子,最后再将试卷交换回来即可。
具体地,假设当前还剩下k只猴子需要处理,递归函数可以定义如下:
int dfs(int k, int i, int j)
{
// 如果i=j,则这种情况不合法,返回0
if (i == j) return 0;
// 如果只剩下一只猴子,则只有一种情况
if (k == 1) return 1;
// 交换第i只和第j只猴子的试卷,然后递归处理剩下的猴子
int res = dfs(k - 1, i, j);
for (int t = 1; t <= k - 2; t++)
{
res += dfs(k - 1, i, i + t) * dfs(k - 1, j, j - t);
}
// 将试卷交换回来
return res;
}
其中,dfs函数的参数k表示当前还剩下k只猴子需要处理,i和j表示要交换试卷的两只猴子的编号。
在主函数中,只需要调用dfs函数,传入参数n和1和2,表示要交换第1只和第2只猴子的试卷,最后输出结果即可。
设符合条件的有f(n)种方案,则,f(1)=0,f(2)=1,递推公式为
f(n)=(n-1)*(f(n-1)+f(n-2));//错排公式
用一个循环就可以求出f(n),时间复杂度为O(N)
#include<stdio.h>
long long int f[21] = {0,0,1};
int main() {
long long int i, n;
for (i = 3; i <= 20; i++) {//数组规模不大,直接全算出来也消耗不了多少时间,主要是方便测试
f[i]=(i-1)*(f[i-1]+f[i-2]);
}
while (printf("输入猴子数量n:"),scanf("%lld", &n) != EOF)//套个循环方便测试
printf("有%lld种方案\n\n", f[n]);
return 0;
}
#include<stdio.h>
int a[21] = {0,0,1};
int main() {
int i,n;
for (i = 3; i <= 20; i++) {
a[i]=(i-1)*(a[i-1]+a[i-2]);
}
scanf("%d",&n);
printf("%d", a[n]);
return 0;
}
在C++中,您可以使用以下方法来指定输出格式:
使用流操作符“<<”来输出变量的值,并使用格式说明符指定输出格式。例如,以下代码将以十进制格式输出整数变量i的值:
c
Copy code
int i = 123;
cout << "i的十进制值为:" << dec << i << endl;
其中,dec是C++标准库中的一个格式说明符,用于指定输出的进制格式为十进制。
使用C++标准库中的iomanip头文件中的格式控制符和操纵符来指定输出格式。例如,以下代码将以定点格式输出浮点数变量f的值,并设置精度为2:
c
Copy code
#include
float f = 3.1415926;
cout << "f的定点格式值为:" << fixed << setprecision(2) << f << endl;
其中,fixed是iomanip头文件中的一个格式控制符,用于指定输出的浮点数格式为定点格式。setprecision(2)是iomanip头文件中的一个操纵符,用于设置输出的浮点数的精度为2。
通过使用以上两种方法,您可以在C++中指定输出格式,并将数据以您所需的方式输出。
基于最新版ChatGPT4的回答,望采纳!!!有其他问题也可以询问我哦💕(最新版更智能,功能更加强大):
您好,根据您提供的问题描述,这是一道组合数学的题目,要求计算 n 个元素的排列中,每个元素都不在它原来的位置上的排列数。
可以使用容斥原理来解决这个问题。首先计算所有排列的数量
�
!
n!,然后减去其中恰好有一个元素不在原来位置上的排列数,再加上恰好有两个元素不在原来位置上的排列数,以此类推。具体地,假设
�
(
�
)
f(k) 表示恰好有
�
k 个元素不在原来位置上的排列数,则有:
�
(
0
)
=
1
,
�
(
�
)
=
(
�
�
)
(
�
−
�
)
!
(
−
1
)
�
,
1
≤
�
≤
�
f(0)=1,f(k)=(
k
n
)(n−k)!(−1)
k
,1≤k≤n
最终的方案数就是所有
�
(
�
)
f(k) 的和。
下面是 C++ 的代码实现,其中使用了递归函数 permute 计算
�
n 的阶乘,使用了 factorial 数组保存了前
�
n 个自然数的阶乘值。另外,为了避免整数溢出,可以使用 long long 类型来存储中间结果。
c++
#include <iostream>
using namespace std;
const int N = 20;
int n;
long long factorial[N+1]; // 存储前N个自然数的阶乘
// 递归计算n的阶乘
void permute(int n, long long &p)
{
if (n == 0) p = 1;
else permute(n-1, p), p *= n;
}
int main()
{
cin >> n;
factorial[0] = 1;
for (int i = 1; i <= n; i++) {
permute(i, factorial[i]); // 计算i的阶乘
factorial[i] *= factorial[i-1]; // 记录前i个自然数的阶乘
}
long long ans = 0;
for (int k = 0; k <= n; k++)
ans += (k % 2 ? -1 : 1) * factorial[n] / factorial[k] * factorial[n-k];
cout << ans << endl;
return 0;
}
希望这些信息能够对您有所帮助,如果您有任何问题,请随时联系我。
该回答引用于gpt与OKX安生共同编写:
你好,这个问题可以使用 C++ 中的递归函数来解决。假设有n只猴子,我们可以从第一只猴子开始,让它选择不修改试卷或者修改除自己以外的其他猴子的试卷。然后,递归地处理剩下的n - 1只猴子即可。
具体实现如下:
#include <iostream>
using namespace std;
int n;
bool used[21];
// index:当前正在处理第几只猴子
// last:上一个被修改的猴子的编号
int dfs(int index, int last)
{
// 第n只猴子已经修改完毕,返回一种方案
if (index == n + 1)
{
return 1;
}
int res = 0;
// 不修改当前猴子的试卷
res += dfs(index + 1, last);
// 修改当前猴子以外的其他猴子的试卷
for (int i = 1; i <= n; i++)
{
if (i != index && i != last && !used[i])
{
used[i] = true; // 标记当前猴子已经被修改过
res += dfs(index + 1, i);
used[i] = false; // 回溯
}
}
return res;
}
int main()
{
cin >> n;
cout << dfs(1, 0) << endl;
return 0;
}
在上面的代码中,我们使用 cout
输出结果,并在结尾添加了一个换行符,这样就可以保证输出格式与题目要求相同。同时,为了更好地展示代码结构,我将注释也一并保留了下来。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
对于这个问题,可以使用递归来解决。假设我们已经知道了 $n-1$ 个猴子的修改方案,现在来考虑第 $n$ 只猴子的方案。因为第 $n$ 只猴子不能修改自己的试卷,所以有两种情况:
第 $n$ 只猴子修改了第 $i$ 只猴子的试卷,其中 $i \in [1, n-1]$,那么问题就转化为了 $n-2$ 只猴子修改 $n-2$ 只猴子的方案数,即 $f(n-2)$。
第 $n$ 只猴子不修改任何一只猴子的试卷,那么问题就转化为了 $n-1$ 只猴子修改 $n-1$ 只猴子的方案数,即 $f(n-1)$。
因此,题目的答案就是 $f(n-1) + (n-1) \times f(n-2)$,其中 $f(1)=0, f(2)=1$。
C++ 代码如下:
如果我的回答解决了您的问题,请采纳!
cpp
#include
using namespace std;
int count(int n, int k) {
if (k == 1) return n - 1;
return count(n - 1, k - 1) * (n - 1) + count(n - 1, k);
}
int main() {
int n;
cin >> n;
cout << count(n, n) << endl;
return 0;
}
cpp
#include
using namespace std;
const int MAXN = 20;
int dp[MAXN+1][MAXN+1];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
dp[i][1] = i - 1;
for (int j = 2; j <= i; j++) {
dp[i][j] = (i - 1) * dp[i-1][j-1] + dp[i-1][j];
}
}
cout << dp[n][n] << endl;
return 0;
}