考察算法基础知识。数组大小为N,若N为偶数,则需要(N-2)/23+1=N/23-2次比较;若N为奇数,则需要比较(N-1)/2*3次比较。偶数先比较前两个数,作为最大值和最小值的初始值,需要一次比较次数。奇数将第一个元素作为最大值和最小值的初始值。再以两个数为一组,首先比较这两个数的大小,然后分别与当前最小值和最大值比较。两个公式可以合并成⌈ 2/3N ⌉−2。
考察排列与组合基础知识。10个元素的集合的子集数有1024个,有7个元素组成的子集数有c(10,7)=c(10,3)=120种,所以答案:120/1024=15/128 B
21题:
#include <cstdio>
int n, d[100];
bool v[100];
int main() {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", d + i);
v[i] = false;
}
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (!v[i]) {
for (int j = i; !v[j]; j = d[j]) {
v[j] = true;
}
++cnt;
}
}
printf("%d
", cnt);
return 0;
}
输入:10 7 1 4 3 2 5 9 8 0 6
输出:6
发现输入先读入点的个数,再读入 d 数组, d 数组是个 00 到 99 这 1010 个点的排列。d 数组的第 ii 个值就是 ii 出边的另一端点,程序求的是这个图中环的个数,共 $64 个。
环分别是(00,77,88),(11),(22,44),(55),(66,99)。
#include <iostream>
using namespace std;
const int N = 110000, P = 10007;
int n;
int a[N], len;
int ans;
void getDivisor() {
len = 0;
for (int i = 1; ① <= n; ++i)
if (n % i == 0) {
a[++len] = i;
if ( ② != i) a[++len] = n / i;
}
}
}
int gcd(int a, int b) {
if (b == 0) {
③ ;
}
return gcd(b, ④ );
}
int main() {
cin >> n;
getDivisor();
ans = 0;
for (int i = 1; i <= len; ++i) {
for (int j = i + 1; j <= len; ++j) {
ans = ( ⑤ ) % P;
}
}
cout << ans << endl;
return 0;
}
题目答案:
1:i*i
2:n/i
3:return a
4:a%b
5:ans+gcd(a[i),a[j]
题目解析:
枚举约数的时候,需要枚举到 n,所以第①空需要填 i * i,i * i <= n 就是枚举到 \sqrt n
n
。
如果 n % i == 0,ii 和 n / in/i 都是 nn 的约数,第 ② 空填 n / i 用于防止得到重复的约数。
第 ③④ 空位于辗转相除法求最大公约数函数里,分别填入 a 和 a % b。
第 ⑤ 空位于枚举约数,求两个约数的最大公约数并更新答案的地方,所以需要填上 ans + gcd(a[i], a[j])。
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int L[N], R[N], a[N];
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
int x;
cin >> x;
① ;
}
for (int i = 1; i <= n; ++i) {
R[i] = ② ;
L[i] = i - 1;
}
for (int i = 1; i <= n; ++i) {
L[ ③ ] = L[a[i]];
R[L[a[i]]] = R[ ④ ];
}
for (int i = 1; i <= n; ++i) {
cout << ⑤ << " ";
}
cout << endl;
return 0;
}
题目答案
1:a[x]=i
2:i+1
3:r[a[i]]
4:a[i]
5:r[i]
题目解析:
考察双向链表的基本操作。程序按照 xx 的值从 11 到 nn 枚举每个值,依次在双向链表中删除该点,删除的时候就可以知道该值左边最近比它大元素的位置和右边最近比它大元素的位置。
第 ① 空是 a 数组的初始化操作,标记每个值的位置,所以需要填 a[x] = i。
第 ② 空是双向链表指针的初始化操作,右指针指向右边相邻的元素,所以需要填 i + 1。
第 ③④ 空是双向链表的删除操作,当前元素右边元素的左指针需要指向左边元素,左边元素的右指针需要指向右边元素,所以分别填 R[a[i]] 和 a[i]。
最后需要输出答案,即 R[i] 的值,所以第 ⑤ 空需要填 R[i]。