当前位置:   article > 正文

第十届蓝桥杯B组C/C++省赛编程题题目及答案解析_第十届蓝桥杯大赛青少年创意编程c++组省赛

第十届蓝桥杯大赛青少年创意编程c++组省赛

目录

试题F:特别数的和

试题G:完全二叉树的权值 

试题H:等差数列 

         试题I:后缀表达式

试题J:灵能传输



试题F:特别数的和

【试题解析】

枚举1-n,取出中满足题意的数累加即可。

  1. #include <iostream>
  2. using namespace std;
  3. const int N = 10010;
  4. int main()
  5. {
  6. int n;
  7. cin >> n;
  8. int res = 0;
  9. for(int i = 1; i <= n; i ++) //枚举1-n的所有数
  10. {
  11. int x = i;
  12. while(x)
  13. {
  14. int t = x % 10; //每次取出末位的数
  15. if(t == 0 || t == 1 || t == 2 || t == 9)
  16. {
  17. res += i;
  18. break;
  19. }
  20. x /= 10; //将末位的数移去
  21. }
  22. }
  23. cout << res;
  24. return 0;
  25. }

试题G:完全二叉树的权值 

【试题解析】

找规律+双指针,双指针i, j依次枚举每层深度的起点和终点,依次记录每层的权值,输出最大权值对应的层数即可。

  1. #include <iostream>
  2. #include <cstring>
  3. #include <climits>
  4. using namespace std;
  5. const int N = 100010;
  6. typedef long long LL;
  7. int q[N];
  8. int n;
  9. int main()
  10. {
  11. cin >> n;
  12. for(int i = 1; i <= n; i ++)
  13. scanf("%d", &q[i]);
  14. LL maxv = INT_MIN, res = 0;
  15. int depth = 1;
  16. for(int i = 1; i <= n; i *= 2) //枚举每一层的起点
  17. {
  18. LL s = 0;
  19. for(int j = i; j <= i * 2 - 1 && j <= n; j ++) //对于每一层的起点i,分析可知终点为i * 2 - 1
  20. {
  21. s += q[j];
  22. }
  23. if(s > maxv)
  24. {
  25. maxv = s, res = depth; //记录最大值及对应的层数
  26. }
  27. depth ++;
  28. }
  29. cout << res;
  30. return 0;
  31. }

试题H:等差数列 

【题目解析】 

两种做法:1.暴力枚举每一个公差d,找到满足题意的最大公差, 根据 (a[n - 1] - a[0]) / d,

a[n - 1]和a[0]已定,取d最大,即可保证项数最小。

                  2.枚举任意两个数的差,为kd(k为整数),求出所有kd的最大公约数,即为最大公差。

两种方法在蓝桥杯官网都能AC,但理论上来说第一种暴力的方法时间复杂度为O(n^{_2{}})会存在被卡数据的情况。

  1. //暴力做法
  2. #include <iostream>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 100010;
  6. int a[N];
  7. int n;
  8. int main()
  9. {
  10. cin >> n;
  11. for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
  12. sort(a, a + n);
  13. int d = a[1] - a[0];
  14. if(a[n - 1] == a[0]) cout << n; //特判公差为0的情况,此时项数最少即为n
  15. for(int j = d; j >= 1; j --)
  16. {
  17. bool falg = true;
  18. for(int i = 1; i < n; i ++)
  19. {
  20. if((a[i] - a[i - 1]) % j)
  21. {
  22. falg = false;
  23. break;
  24. }
  25. }
  26. if(falg == true)
  27. {
  28. cout << (a[n - 1] - a[0]) / j + 1;
  29. break;
  30. }
  31. }
  32. return 0;
  33. }
  1. //求kd最大公约数的方法
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <cstring>
  5. using namespace std;
  6. const int N = 1e5 + 10;
  7. int gcd(int a, int b)
  8. {
  9. return b? gcd(b, a % b) : a;
  10. }
  11. int a[N];
  12. int n;
  13. int main()
  14. {
  15. cin >> n;
  16. for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
  17. sort(a, a + n);
  18. int d = a[1] - a[0];
  19. if(d == 0)
  20. cout << n;
  21. else
  22. {
  23. for(int i = 1; i < n; i ++)
  24. {
  25. d = gcd(d, a[i] - a[0]);
  26. }
  27. cout << (a[n - 1] - a[0]) / d + 1;
  28. }
  29. return 0;
  30. }

 

试题I:后缀表达式

【试题解析】

贪心,摘自AcWing 1247. 后缀表达式+思维图解 - AcWing 的图解,分析可知当M > 0时,我们总可以将M个‘ - ’号化为一个,此时我们只需减去A中的最小值,再加上A中最大值,剩余的数如果大于0我们就加上,小于0就减去。(代码很简单,难在理解如何将M个' - '化为一个' - ')

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <cmath>
  5. using namespace std;
  6. typedef long long LL;
  7. int n, m, k;
  8. const int N = 2e5 + 10;
  9. int a[N];
  10. int main()
  11. {
  12. cin >> n >> m;
  13. k = n + m + 1;
  14. for(int i = 0; i < k; i ++) scanf("%d", &a[i]);
  15. sort(a, a + k);
  16. LL res = 0;
  17. if(!m)
  18. for(int i = 0; i < k; i ++ ) res += a[i];
  19. else
  20. {
  21. res = res + a[k - 1] - a[0];
  22. for(int i = 1; i < k - 1; i ++)
  23. res += abs(a[i]); //加上大于0的数和减去小于0的数都可以记为加上该数的绝对值
  24. }
  25. cout << res;
  26. return 0;
  27. }

试题J:灵能传输

【试题解析】

又是一道贪心题,这题没写,转发AcWing 1248. 灵能传输--详细说一些细节 - AcWing大佬的题解

  1. #include "bits/stdc++.h"
  2. using namespace std;
  3. typedef long long LL;
  4. const int N = 3e5 + 10;
  5. int t, n;
  6. LL s[N], a[N]; // s为前缀和数组 a为存放前缀和顺序的数组
  7. bool st[N];
  8. int main()
  9. {
  10. cin >> t;
  11. while (t--)
  12. {
  13. cin >> n;
  14. memset(st, 0, sizeof st);
  15. for (int i = 1; i <= n; i++)
  16. cin >> s[i], s[i] += s[i - 1];
  17. LL s0 = s[0], sn = s[n];
  18. if (s0 > sn)
  19. swap(s0, sn);
  20. sort(s, s + n + 1);
  21. // 寻找排完序后s0和sn的位置
  22. // 如果s0和sn相同的话则前面的为s0 后面的为sn
  23. for (int i = 0; i <= n; i++)
  24. if (s[i] == s0)
  25. {
  26. s0 = i;
  27. break;
  28. }
  29. for (int i = n; i >= 0; i--)
  30. if (s[i] == sn)
  31. {
  32. sn = i;
  33. break;
  34. }
  35. int l = 0, r = n;
  36. for (int i = s0; i >= 0; i -= 2)
  37. {
  38. a[l++] = s[i];
  39. st[i] = 1;
  40. }
  41. for (int i = sn; i <= n; i += 2)
  42. {
  43. a[r--] = s[i];
  44. st[i] = 1;
  45. }
  46. for (int i = 0; i <= n; i++)
  47. if (!st[i])
  48. a[l++] = s[i];
  49. LL res = 0;
  50. for (int i = 1; i <= n; i++)
  51. res = max(res, abs(a[i] - a[i - 1]));
  52. cout << res << endl;
  53. }
  54. return 0;
  55. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/48834
推荐阅读
相关标签
  

闽ICP备14008679号