CSP 2020 入门级第一轮重要题目

设 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开始连续自然数的平方和公式:n*(n+1)*(2n+1)*1/6)

另外一列也是一样的,为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

将所选区间的右端点更新到新选择的区间的右端点

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值