设 A 是 n 个实数的数组,考虑下面的递归算法:
请问算法 XYZ 的输出是什么?()
XYZ (A[1..n])
if n=1 then return A[1]
else temp ← XYZ (A[1..n-1])
if temp < A[n]
then return temp
else return A[n]
A. A数组的平均
B. A数组的最小值
C. A数组的中值
D. A数组的最大值
答案:B
每次递归返回的都是temp和A[n]更小的,所以是返回的最小值
5 个小朋友并排站成一列,其中有两个小朋友是双胞胎,如果要求这两个双胞胎必须相邻,则有( )种不同排列方法?
A. 48
B. 36
C. 24
D. 72
答案:A
两个人非要一起站,就可以把这两个人看成一个人,用排列,A44计算得到4*3*2*1得到24中可能,但是站在一起的两个人之间还有A12种可能,一共就是A44*A21种就是24*2=48种。
10 个三好学生名额分配到 77 个班级,每个班级至少有一个名额,一共有( )种不同的分配方案。
A. 84
B. 72
C. 56
D. 504
答案:A
每班先给一个名额,问题就变成了7个班级分三个名额。
三个名额:可以分成三份,两份,或者一份。
总方案数就是:C 73 +C 72 * 2 +C 71 = 35 + 42 + 7 = 84
阅读代码的问题
#include <algorithm>
#include <iostream>
using namespace std;
int n;
int d[50][2];
int ans;
void dfs(int n, int sum) {
if (n == 1) {
ans = max(sum, ans);
return;
}
for (int i = 1; i < n; ++i) {
int a = d[i - 1][0], b = d[i - 1][1];
int x = d[i][0], y = d[i][1];
d[i - 1][0] = a + x;
d[i - 1][1] = b + y;
for (int j = i; j < n - 1; ++j)
d[j][0] = d[j + 1][0], d[j][1] = d[j + 1][1];
int s = a + x + abs(b - y);
dfs(n - 1, sum + s);
for (int j = n - 1; j > i; --j)
d[j][0] = d[j - 1][0], d[j][1] = d[j - 1][1];
d[i - 1][0] = a, d[i - 1][1] = b;
d[i][0] = x, d[i][1] = y;
}
}
int main() {
cin >> n;
for (int i = 0; i < n; ++i)
cin >> d[i][0];
for (int i = 0; i < n;++i)
cin >> d[i][1];
ans = 0;
dfs(n, 0);
cout << ans << endl;
return 0;
}
相当于把一个二维数组的第一列和第0列看作两个一维数组,然后发现递归dfs()后面的部分都是回溯,前面部分就是第0列计算和,第1列计算差。计算结果向前移,代替原来的位置。
1.若输入 nn 为 2020,接下来的输入全为 0,则输出为 0。( )
正确,因为0无论是加还是减,计算结果一定是0。
2.若输入的 nn 为 15,接下来的输入是 15 到 11,以及 15 到 11,则输出为( )。
答案:2240
做加法的那一列会从15+14开始,每迭代一次都加上前一个,直到加到一,最后加法部分的结果就是15的2次方一直加到1的二次方(补充一下从1开始连续自然数的平方和公式:)
另外一列也是一样的,为15+1到15到1的和。每次迭代加上上一个“新生成的”数-1.最后答案是15∗13+14∗12+13∗11+...+4∗2+3∗1+1∗14=1015
然后把两列的和加起来,得到2240.
最后一道
#include <iostream>
using namespace std;
const int MAXN = 5000;
int n, m;
struct segment { int a, b; } A[MAXN];
void sort() // 排序
{
for (int i = 0; i < n; i++)
for (int j = 1; j < n; j++)
if (①)
{
segment t = A[j];
②
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> A[i].a >> A[i].b;
sort();
int p = 1;
for (int i = 1; i < n; i++)
if (③)
A[p++] = A[i];
n = p;
int ans = 0, r = 0;
int q = 0;
while (r < m)
{
while (④)
q++;
⑤;
ans++;
}
cout << ans << endl;
return 0;
}
①处应填():
A. A[j].b>A[j-1].b
B. A[j].a<A[j-1].a
C. A[j].a>A[j-1].a
D. A[j].b<A[j-1].b
答案: B
根据左端点升序排序。
②处应填():
A. A[j+1]=A[j];A[j]=t;
B. A[j-1]=A[j];A[j]=t;
C. A[j]=A[j+1];A[j+1]=t;
D. A[j]=A[j-1];A[j-1]=t;
答案:D
这就是手动swap()函数。
⑤处应填():
A. r=max(r,A[q+1].b)
B. r=max(r,A[q].b)
C. r=max(r,A[q+1].a)
D. q++
答案:B
将所选区间的右端点更新到新选择的区间的右端点