当前位置:   article > 正文

2021蓝桥杯省赛b组c/c++(蓝桥杯备战)_蓝桥杯省赛2021

蓝桥杯省赛2021

今天是2023.4.5号,距离蓝桥杯还有3天,自己就刷了两套真题,刷题的过程中还有好多不会的,真的哭了,感觉第一次蓝桥杯没有准备好,寒假也荒废了,算法也学的好慢。题目感觉好多都没有思路。我感觉还是自己总结的少了,所以最近开始写起了博客,来总结一下,顺便记录一下自己的刷题记录。好了,不说闲话了,开始正题。

引用:蓝桥杯——2021第十二届C/C++真题[省赛][B组]_蓝桥杯c++历年真题_接受平凡 努力出众的博客-CSDN博客

【蓝桥杯真题】2021年蓝桥杯省赛B组题目解析+代码(C/C++)_蓝桥杯2021年省赛b组_我的程序跑快快的博客-CSDN博客

A:空间:

在这里插入图片描述

基础知识:1GB=1024MB,1MB=1024KB,1KB=1024字节,1字节=8位

所以答案为256*1024*1024/4=67108864

B:卡片

在这里插入图片描述

思路:开一个数组,将a0,a1到a9赋值为2021,然后遍历数组+分离数字即可,但要注意题意:问的是可以拼到哪个数,不是不能拼成那个数。然而我就错了..

代码如下:

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read(){
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while(ch < '0' || ch > '9'){
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while(ch >= '0' && ch <= '9'){
  26. x = (x<<1) + (x<<3) + (ch^48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if(num) {
  33. print(num/10);
  34. putchar(num%10+'0');
  35. }
  36. }
  37. int a[10]={2021,2021,2021,2021,2021,2021,2021,2021,2021};
  38. int flag=0;
  39. int main(){
  40. for(int i=1;i<=10000;i++){
  41. int n=i;
  42. while(n!=0){
  43. if(a[n%10]>0){
  44. a[n%10]--;
  45. n=n/10;
  46. }else{
  47. flag=0;
  48. break;
  49. }
  50. }
  51. if(flag==1){
  52. printf("%d\n",i);
  53. break;
  54. }
  55. }
  56. return 0;
  57. }

 C:直线(别人图):

在这里插入图片描述

思路:直线有多种表示方法:如Ax+By+C=0,或者y=kx+b,用set存储即可;但需要注意x1==x2或者y1==y2的情况,这两种情况单独考虑即可。

采用Ax+By+C=0,一定要记得去除最小公因数,不然答案会多,本人就是忘记了..代码如下:

  1. #include<iostream>
  2. #include<set>
  3. using namespace std;
  4. typedef pair<double, double> PII;
  5. typedef pair<PII, double> PIII;
  6. set<PIII> ss;
  7. int gcd(int a, int b)
  8. {
  9. if (b == 0) return a;
  10. return gcd(b, a % b);
  11. }
  12. int main()
  13. {
  14. for (int x1 = 0; x1 <= 19; x1++)
  15. {
  16. for (int y1 = 0; y1 <= 20; y1++)
  17. {
  18. for (int x2 = 0; x2 <= 19; x2++)
  19. {
  20. for (int y2 = 0; y2 <= 20; y2++)
  21. {
  22. if (x1 != x2 && y1 != y2)
  23. {
  24. double a = x2 - x1;
  25. double b = y1 - y2;
  26. double c = y2 * x1 - x2 * y1;
  27. double m = gcd(gcd(a, b), c);//一定要记得除a,b,c的最小共因数,不然答案会多
  28. ss.insert({ { a / m,b / m }, c / m });
  29. //ss.insert(a);
  30. }
  31. }
  32. }
  33. }
  34. }
  35. cout << ss.size() + 20 + 21;
  36. return 0;
  37. }

如果采用y=kx+b方法在运算的过程中很有可能会掉精度,所以不推荐使用。

D :货物摆放在这里插入图片描述

本题可以使用暴力,但是纯暴力是过不去的,程序运行半天也没出结果,但暴力经过优化之后就可以过了

暴力思路:将n分解为a,b,c,设a<=b<=c然后就可以在循环方面做优化了:

代码如下:

  1. #include<iostream>
  2. using namespace std;
  3. #define n 2021041820210418
  4. //n=a*b*c
  5. typedef long long ll;
  6. int ans = 0;
  7. int main()
  8. {
  9. for (ll a = 1; a * a * a <= n; a++)//保证a<=b<=c;
  10. {
  11. if (n % a == 0)
  12. {
  13. for (ll b = a; a * b * b <= n; b++)
  14. {
  15. if (n / a % b == 0)
  16. {
  17. ll c = n / a / b;
  18. if (a == b && a == c){
  19. ans=ans+1;
  20. continue;
  21. }
  22. else if (a == b || a == c || c == b) {
  23. ans += 3;
  24. continue;
  25. }
  26. else {
  27. ans += 6;
  28. continue;
  29. }
  30. }
  31. }
  32. }
  33. }
  34. cout << ans << endl;
  35. return 0;
  36. }

其他思路:如果不考虑暴力的话,可以采用数学的方法,即质因数分解,质因数分解的代码如下:

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read(){
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while(ch < '0' || ch > '9'){
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while(ch >= '0' && ch <= '9'){
  26. x = (x<<1) + (x<<3) + (ch^48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if(num) {
  33. print(num/10);
  34. putchar(num%10+'0');
  35. }
  36. }
  37. ll n=2021041820210418;
  38. int main(){
  39. //质因数分解
  40. for(ll i=2;i<=n;i++){
  41. if(n%i==0){
  42. printf("%lld ",i);
  43. n=n/i;
  44. i=1;
  45. }
  46. }
  47. return 0;
  48. }

将n分解得到2 3 3 3 17 131 2857 5882353;即n=2*3^3*17*131*2857*5882353

先考虑2,17,131,2857,5882353这5个数,一共三个空,每个数有三种可能:即3^5

再来考虑三个3,可以枚举每一个三的方法:

有 3 0 0,0 3 0, 0 0 3, 2 1 0 ,2 0 1, 1 2 0, 0 2 1, 1 2 0, 2 1 0,1 1 1共十种

注意:还有1的情况,当某个空没有放数时,1就补充了。

所以一共有10*3^5方法 

E:在这里插入图片描述

思路:佛洛依德算法,虽然很慢,但简单,我不会,所以学了下:

代码如下:    注意a[i][i]赋值为0!!!

i和j的最小公倍数为i*j/gcd(i,j);

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read() {
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while (ch < '0' || ch > '9') {
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while (ch >= '0' && ch <= '9') {
  26. x = (x << 1) + (x << 3) + (ch ^ 48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if (num) {
  33. print(num / 10);
  34. putchar(num % 10 + '0');
  35. }
  36. }
  37. int gcd(int a, int b) {
  38. if (b == 0)return a;
  39. return gcd(b,a%b);
  40. }
  41. int a[2050][2050];
  42. int main() {
  43. for (int i = 1; i <= 2021; i++) {
  44. for (int j = 1; j <= 2021; j++) {
  45. if (abs(i - j) > 21) {
  46. a[i][j] = a[j][i] = inf;
  47. } else {
  48. if (i == j) {
  49. a[i][j] = a[j][i] = 0;
  50. } else {
  51. a[i][j] = a[j][i] = i * j / gcd(i, j);
  52. }
  53. }
  54. }
  55. }
  56. for(int k=1;k<=2021;k++){
  57. for(int i=1;i<=2021;i++){
  58. for(int j=1;j<=2021;j++){
  59. if(a[i][k]+a[k][j]<a[i][j]){
  60. a[i][j]=a[i][k]+a[k][j];
  61. }
  62. }
  63. }
  64. }
  65. printf("%d\n",a[2021][1]);
  66. return 0;
  67. }

F:签到题直接跳过在这里插入图片描述 

G:砝码称重在这里插入图片描述

在考场上很难想到状态转移方程,如果要骗分的话,可以使用搜索。搜索是干什么的?任何问题都可以有搜索解决!!如果没有思路就搜啊!代码如下,注意:打标记的时候一定要加上绝对值,因为左右两盘是等效的!!!

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read() {
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while (ch < '0' || ch > '9') {
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while (ch >= '0' && ch <= '9') {
  26. x = (x << 1) + (x << 3) + (ch ^ 48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if (num) {
  33. print(num / 10);
  34. putchar(num % 10 + '0');
  35. }
  36. }
  37. int n;
  38. int a[105];
  39. int vis[100005];
  40. void dfs(int s, int i) {
  41. if (i == n + 1) {
  42. // if (s > 0) {
  43. // vis[s] = 1;
  44. // }
  45. return ;
  46. }
  47. vis[abs(s)]=1;//注意加绝对值,s是由上一个dfs来的所以可能为负数!!
  48. vis[abs(s+a[i])]=1;
  49. vis[abs(s-a[i])]=1;
  50. dfs(s + a[i], i + 1);
  51. dfs(s, i + 1);
  52. dfs(s - a[i], i + 1);
  53. }
  54. int main() {
  55. scanf("%d", &n);
  56. int sum = 0;
  57. for (int i = 1; i <= n; i++) {
  58. scanf("%d", &a[i]);
  59. sum = sum + a[i];
  60. }
  61. dfs(0, 1);
  62. int ans = 0;
  63. for (int i = 1; i <= sum; i++) {
  64. if (vis[i] == 1) {
  65. ans++;
  66. }
  67. }
  68. printf("%d\n", ans);
  69. return 0;
  70. }

正确的思路就是dp的背包问题了,yan式dp分析法如下

 1,设sum为n件物品的总重量,如果采用就地滚动的方法,需要两次就地滚动,但要注意sum循环的方向,代码如下\

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read() {
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while (ch < '0' || ch > '9') {
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while (ch >= '0' && ch <= '9') {
  26. x = (x << 1) + (x << 3) + (ch ^ 48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if (num) {
  33. print(num / 10);
  34. putchar(num % 10 + '0');
  35. }
  36. }
  37. ll ans = 0;
  38. int dp[100105];
  39. int vis[100105];
  40. int a[105];
  41. int main() {
  42. int n;
  43. scanf("%d", &n);
  44. int sum = 0;
  45. for (int i = 1; i <= n; i++) {
  46. scanf("%d", &a[i]);
  47. sum = sum + a[i];
  48. }
  49. dp[0] = 1;
  50. vis[0]=1;
  51. for (int i = 1; i <= n; i++) {
  52. for (int j = sum; j >= a[i]; j--) {
  53. dp[j] = dp[j - a[i]] | dp[j];//dp[j-a[i]等效dp[i-1][j-a[i]];
  54. if (dp[j] == 1) {
  55. vis[j] = 1;
  56. }
  57. }
  58. }
  59. for (int i = 1; i <= n; i++) {
  60. for (int j =0;j<=sum; j++) {
  61. dp[j] = dp[j] | dp[j + a[i]];//dp[j+a[i]]等效于dp[i-1][j+a[i]];
  62. if (dp[j] == 1 ) {
  63. vis[j] = 1;
  64. }
  65. }
  66. }
  67. for(int i=1;i<=sum;i++){
  68. if(vis[i]){
  69. ans++;
  70. }
  71. }
  72. printf("%lld\n", ans);
  73. return 0;
  74. }

2.如果用dp[i][j]=dp[i-1][j] | dp[i-1][j+a[i]] |dp[i-1][j-a[i]]时,要注意j-a[i]可能为负数,但左右两边又是等效的,所以dp[i][j]=dp[i-1][j] | dp[i-1][j+a[i]] |dp[i-1][abs(j-a[i])],这题跟登录—专业IT笔试面试备考平台_牛客网非常相似

代码如下

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read() {
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while (ch < '0' || ch > '9') {
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while (ch >= '0' && ch <= '9') {
  26. x = (x << 1) + (x << 3) + (ch ^ 48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if (num) {
  33. print(num / 10);
  34. putchar(num % 10 + '0');
  35. }
  36. }
  37. ll ans = 0;
  38. int dp[105][100105];//前i个数重量为j;
  39. int a[105];
  40. int main() {
  41. int n;
  42. scanf("%d", &n);
  43. int sum = 0;
  44. for (int i = 1; i <= n; i++) {
  45. scanf("%d", &a[i]);
  46. sum = sum + a[i];
  47. }
  48. dp[0][0] = 1;
  49. int ans = 0;
  50. for (int i = 1; i <= n; i++) {
  51. for (int j = 1; j <= sum; j++) {
  52. dp[i][j]=dp[i-1][j]|dp[i-1][j+a[i]]|dp[i-1][abs(j-a[i])];
  53. }
  54. }
  55. for (int j = 1; j <= sum; j++) {
  56. if (dp[n][j])ans++;
  57. }
  58. printf("%d\n", ans);
  59. return 0;
  60. }

H:在这里插入图片描述

 我没啥思路,只能暴力骗分,过了5个样例,骗了9分,开心,代码如下,但我在测试的过程中,如果把dp数组开到dp[3000][3000]就过了2个样例,难道还跟数组的大小有关?不明白..

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read(){
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while(ch < '0' || ch > '9'){
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while(ch >= '0' && ch <= '9'){
  26. x = (x<<1) + (x<<3) + (ch^48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if(num) {
  33. print(num/10);
  34. putchar(num%10+'0');
  35. }
  36. }
  37. ll dp[1020][1002];
  38. int main(){
  39. int n;
  40. scanf("%d",&n);
  41. if(n==1){
  42. printf("1\n");
  43. return 0;
  44. }
  45. for(int i=1;i<=1000;i++){
  46. dp[i][1]=dp[i][i]=1;
  47. }
  48. for(int i=3;i<=1000;i++){
  49. for(int j=2;j<=i-1;j++){
  50. dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
  51. if(dp[i][j]==n){
  52. cout<<(1+i-1)*(i-1)/2+j;
  53. return 0;
  54. }
  55. }
  56. }
  57. return 0;
  58. }

正确思路:蓝桥杯——2021第十二届C/C++真题[省赛][B组]_蓝桥杯c++历年真题_接受平凡 努力出众的博客-CSDN博客

自己写的代码

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<stack>
  8. #include<deque>
  9. #include<vector>
  10. #include<map>
  11. #include<set>
  12. #include <utility>
  13. using namespace std;
  14. typedef long long ll ;
  15. #define pii pair<int,int>
  16. const int inf = 0x3f3f3f3f;
  17. inline int read(){
  18. int x = 0, f = 1;
  19. char ch = getchar();
  20. while(ch < '0' || ch > '9'){
  21. if (ch == '-')
  22. f = -1;
  23. ch = getchar();
  24. }
  25. while(ch >= '0' && ch <= '9'){
  26. x = (x<<1) + (x<<3) + (ch^48);
  27. ch = getchar();
  28. }
  29. return x * f;
  30. }
  31. void print(__int128 num) {
  32. if(num) {
  33. print(num/10);
  34. putchar(num%10+'0');
  35. }
  36. }
  37. ll n;
  38. ll calc(ll a,ll b){
  39. ll ans=1;
  40. for(ll i=a,j=1;j<=b;i--,j++){
  41. ans=ans*i/j;
  42. if(ans>n)return ans;
  43. }
  44. return ans;
  45. }
  46. bool check(int k){
  47. ll left=2*k;
  48. ll right=max(left,n);
  49. while(left<=right){
  50. ll mid=(left+right)/2;
  51. if(calc(mid,k)>=n){
  52. right=mid-1;
  53. }else{
  54. left=mid+1;
  55. }
  56. }
  57. if(calc(right+1,k)==n){
  58. cout<<(right+2)*(right+1)/2+k+1;
  59. return 1;
  60. }else{
  61. return 0;
  62. }
  63. }
  64. int main(){
  65. cin>>n;
  66. for(int i=16;i>=0;i--){
  67. if(check(i)){
  68. break;
  69. }
  70. }
  71. return 0;
  72. }

最后I和J题,实在不想做了,通过暴力骗点分吧。

总结:考察的算法:dp,二分,搜索,最短路,数论,图论等等

题目感觉不是很难(事后诸葛亮,考试时蒙圈),但考察的很细节啊

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号