题目连接:第九届蓝桥杯试题 C\JAVA


第一题:第几天

2018年第九届蓝桥杯B组题解

答案:125

很简单的数一数就好了,但是我当时可能没带脑子,按2010年算的124天。


第二题:明码

2018年第九届蓝桥杯B组题解

答案:387420489

按着题目把这些数转换成8字节的二进制数就可以了,负数的二进制是补码。可以自己写个函数实现一下,实际效果图:

2018年第九届蓝桥杯B组题解

2018年第九届蓝桥杯B组题解

还可以用bitset,将一个数转换成8位的二进制数,不足用0补位,然后再将bitset数转换成string然后输出。

实现代码:

[cpp] view plain copy
  1. #include <bits/stdc++.h>  
  2. using namespace std;  
  3. int main()  
  4. {  
  5.     int n,m;  
  6.     string str1,str2;  
  7.     while(cin>>n>>m){  
  8.         bitset<8> b(n);  
  9.         str1 = b.to_string();  
  10.         int len1 = str1.length();  
  11.         for(int i=0;i<len1;i++){  
  12.           if(str1[i] == '0')printf(" ");  
  13.           else printf("*");  
  14.         }  
  15.         bitset<8> c(m);  
  16.         str2 = c.to_string();  
  17.         int len2 = str2.length();  
  18.         for(int i=0;i<len2;i++){  
  19.           if(str2[i] == '0')printf(" ");  
  20.           else printf("*");  
  21.         }  
  22.         printf("\n");  
  23.     }  
  24.     return 0;  
  25. }  


第三题:乘积尾零

2018年第九届蓝桥杯B组题解

答案:31

之前计蒜客的第五次模拟赛有道题是求n!末尾有多少个0,那道题就是求1-n的因子里有多少个5。因为想要出现0,只有当有2和5出现的时候,才会出现0,所以我们只需要求出这么多数,能分解出多少个2和5,小的那个数就是结果。

实现代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.   int n;  
  7.   int num1 = 0;  
  8.   int num2 = 0;  
  9.   while(cin>>n){  
  10.     while(1){  
  11.       if(n % 2 == 0){  
  12.         n /= 2;  
  13.         num1++;  
  14.       }  
  15.        else if(n % 5 == 0){  
  16.         n /= 5;  
  17.         num2++;  
  18.       }  
  19.       else {  
  20.         break;  
  21.       }  
  22.     }  
  23.   }  
  24.   printf("%d\n",num1>num2?num2:num1);  
  25.   return 0;  
  26. }  

第四题:测试次数

2018年第九届蓝桥杯B组题解

答案:19

这是一道谷歌的面试题,应该用dp而不是二分。谷歌面试题:丢鸡蛋

第五题:快速排序

2018年第九届蓝桥杯B组题解

答案:a,i+1,r,k-(i-l+1)

虽然填写别的答案也能过样例,但是这道题的要求是时间复杂度为O(n)。

第六题:递增三元组

2018年第九届蓝桥杯B组题解

可以先对三个数组排序,然后遍历数组b,查找a数组中有多少个小于b[i]的,c数组中有多少个大于b[i]的。

还有就是可以直接线性求出答案,即a[x]表示第一个序列中,有多少个数字等于x,b[],c[]同理那么有:
for i = 100000 → 0
c[i] = c[i]+c[i+1]
b[i] = b[i]*c[i+1]+b[i+1]
a[i] = a[i]*b[i+1]+a[i+1]

最后a[0]就是答案

二分方法实现代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. const int MAXN = 100005;  
  7. int a[MAXN],b[MAXN],c[MAXN];  
  8. int n,sum;  
  9.   
  10. int main()  
  11. {  
  12.   scanf("%d",&n);  
  13.   for(int i=0;i<n;i++)scanf("%d",&a[i]);  
  14.   for(int i=0;i<n;i++)scanf("%d",&b[i]);  
  15.   for(int i=0;i<n;i++)scanf("%d",&c[i]);  
  16.   sort(a,a+n);  
  17.   sort(b,b+n);  
  18.   sort(c,c+n);  
  19.   sum = 0;  
  20.   for(int i=0;i<n;i++){  
  21.     int x = (lower_bound(a,a+n,b[i]) - a);  
  22.     int y = (n - (upper_bound(c,c+n,b[i]) - c));  
  23.     sum += x*y;  
  24.   }  
  25.   printf("%d\n",sum);  
  26.   return 0;  
  27. }  


第七题:螺旋折线

2018年第九届蓝桥杯B组题解

2018年第九届蓝桥杯B组题解

这道题就把四个象限分一下,然后找规律递推公式就OK了。


第八题:日志统计

2018年第九届蓝桥杯B组题解

这道题就是模拟一下,按id和时间排序,把相同的id,以时间递增的情况排序,然后暴力枚举每个id的赞数,当在规定的时间范围内赞数大于k,标记一下,然后递增输出id就好了。我也不知道我写的对不对,所以就不上代码了。。。


第九题:全球变暖

2018年第九届蓝桥杯B组题解

       这道题应该会有不少人和我一样理解成了最后还剩多少个岛吧。暴力杯变成了阅读理解杯....对于这道题,我们可以用bfs搜索一下把起初的每个岛屿都编上号,顺便把可能会被淹没的岛屿标记下来,然后我是倒着再遍历一遍地图,只要有没有完全淹没的岛屿,就让岛屿数--,最后就剩下完全淹没的岛屿数了。还有一种情况就是有人提到的一个岛屿淹没完以后变成了两个岛屿,那么就在这特判一下就好了。

实现代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <queue>  
  5. using namespace std;  
  6. struct Node{  
  7.   int x,y;  
  8.   int num;  
  9. }Now,Next,S;  
  10. char MAP[1005][1005];  
  11. int vis[1005][1005];  
  12. int dir[4][2] = {1,0,0,1,-1,0,0,-1};  
  13. int n,sum;  
  14.   
  15. bool in(int x,int y){  
  16.   if(x >= 0 && y >= 0 && x < n && y < n)return true;  
  17.   return false;  
  18. }  
  19.   
  20. bool Check(int x,int y){  
  21.   for(int i=0;i<4;i++){  
  22.     int X = x + dir[i][0];  
  23.     int Y = y + dir[i][1];  
  24.     if(MAP[X][Y] == '.' && in(X,Y))return true;  
  25.   }  
  26.   return false;  
  27. }  
  28.   
  29. void bfs(){  
  30.   queue<Node> q;  
  31.   S.num = sum;  
  32.   q.push(S);  
  33.   while(!q.empty()){  
  34.     Now = q.front();  
  35.     q.pop();  
  36.     if(Check(Now.x,Now.y)){  
  37.       vis[Now.x][Now.y] = 1;  
  38.     }  
  39.     for(int i=0;i<4;i++){  
  40.       Next.x = Now.x + dir[i][0];  
  41.       Next.y = Now.y + dir[i][1];  
  42.       if(in(Next.x,Next.y) && MAP[Next.x][Next.y] == '#' && vis[Next.x][Next.y] != 1){  
  43.         if(vis[Next.x][Next.y] == 0)vis[Next.x][Next.y] = 2;  
  44.         Next.num = Now.num;  
  45.         q.push(Next);  
  46.       }  
  47.     }  
  48.   }  
  49.   sum++;  
  50.   return ;  
  51. }  
  52.   
  53. int main()  
  54. {  
  55.   scanf("%d",&n);  
  56.   for(int i=0;i<n;i++){  
  57.     scanf("%s",MAP[i]);  
  58.   }  
  59.   memset(vis,0,sizeof(vis));  
  60.   sum = 0;  
  61.   for(int i=0;i<n;i++){  
  62.     for(int j=0;j<n;j++){  
  63.       if(MAP[i][j] == '#'){  
  64.         if(vis[i][j] != 0)continue;  
  65.         S.x = i;  
  66.         S.y = j;  
  67.         bfs();  
  68.       }  
  69.     }  
  70.   }  
  71.   for(int i=n-1;i>=0;i--){  
  72.     for(int j=n-1;j>=0;j--){  
  73.       if(MAP[i][j] == '#' && vis[i][j] == 2){  
  74.         sum--;  
  75.       }  
  76.     }  
  77.   }  
  78.   printf("%d\n",sum>0?sum:0);  
  79.   return 0;  
  80. }  


第十题:乘积最大

2018年第九届蓝桥杯B组题解


最后一道题我也不会写,当时是随便暴力了一下过了样例就交了,看了一下别人的题解,确实再给我4个小时我也写不出来...

仔细思考你会发现其实最终答案为负数只有两种情况
①k=n,这n个数都是负数并且n是奇数
②k是奇数,并且这n个数都是负数
其它情况下答案一定为正或者0
为什么呢?一个很简单的证明就是如果你结果为负数,那么你一定可以通过少乘一个负数多乘一个正数,或者少乘一个正数多乘一个负数把答案变成正的

然后正数的情况就好办了
一个很完美的方法就是所有负数取绝对值从大到小排序,所有正数从大到小排序
然后暴力负数选多少个,中间取个最大的就行了
但是这样你肯定不能取模,因为取模就错了,然而直接乘会爆long long
熟练的话你可以写个大整数乘法,不过肯定会超时所以要FFT优化乘法
不会FFT怎么办?
还是将所有负数取绝对值从大到小排序,所有正数从大到小排序
然后一个一个取,每次都取当前最大的数
如果最后刚好为整数,那完美直接输出

如果最后为负数就说明你要调整一下,也就是少乘一个负数多乘一个正数,或者少乘一个正数多乘一个负数,这个时候你只要比一下哪个更大就应该ok!


        明年再战...

版权声明:欢迎转载,若转载,请标明出处,如有错误,请指点,也欢迎大佬们给出优化方法 https://blog.csdn.net/Charles_Zaqdt/article/details/79786821

题目连接:第九届蓝桥杯试题 C\JAVA


第一题:第几天

2018年第九届蓝桥杯B组题解

答案:125

很简单的数一数就好了,但是我当时可能没带脑子,按2010年算的124天。


第二题:明码

2018年第九届蓝桥杯B组题解

答案:387420489

按着题目把这些数转换成8字节的二进制数就可以了,负数的二进制是补码。可以自己写个函数实现一下,实际效果图:

2018年第九届蓝桥杯B组题解

2018年第九届蓝桥杯B组题解

还可以用bitset,将一个数转换成8位的二进制数,不足用0补位,然后再将bitset数转换成string然后输出。

实现代码:

[cpp] view plain copy
  1. #include <bits/stdc++.h>  
  2. using namespace std;  
  3. int main()  
  4. {  
  5.     int n,m;  
  6.     string str1,str2;  
  7.     while(cin>>n>>m){  
  8.         bitset<8> b(n);  
  9.         str1 = b.to_string();  
  10.         int len1 = str1.length();  
  11.         for(int i=0;i<len1;i++){  
  12.           if(str1[i] == '0')printf(" ");  
  13.           else printf("*");  
  14.         }  
  15.         bitset<8> c(m);  
  16.         str2 = c.to_string();  
  17.         int len2 = str2.length();  
  18.         for(int i=0;i<len2;i++){  
  19.           if(str2[i] == '0')printf(" ");  
  20.           else printf("*");  
  21.         }  
  22.         printf("\n");  
  23.     }  
  24.     return 0;  
  25. }  


第三题:乘积尾零

2018年第九届蓝桥杯B组题解

答案:31

之前计蒜客的第五次模拟赛有道题是求n!末尾有多少个0,那道题就是求1-n的因子里有多少个5。因为想要出现0,只有当有2和5出现的时候,才会出现0,所以我们只需要求出这么多数,能分解出多少个2和5,小的那个数就是结果。

实现代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.   int n;  
  7.   int num1 = 0;  
  8.   int num2 = 0;  
  9.   while(cin>>n){  
  10.     while(1){  
  11.       if(n % 2 == 0){  
  12.         n /= 2;  
  13.         num1++;  
  14.       }  
  15.        else if(n % 5 == 0){  
  16.         n /= 5;  
  17.         num2++;  
  18.       }  
  19.       else {  
  20.         break;  
  21.       }  
  22.     }  
  23.   }  
  24.   printf("%d\n",num1>num2?num2:num1);  
  25.   return 0;  
  26. }  

第四题:测试次数

2018年第九届蓝桥杯B组题解

答案:19

这是一道谷歌的面试题,应该用dp而不是二分。谷歌面试题:丢鸡蛋

第五题:快速排序

2018年第九届蓝桥杯B组题解

答案:a,i+1,r,k-(i-l+1)

虽然填写别的答案也能过样例,但是这道题的要求是时间复杂度为O(n)。

第六题:递增三元组

2018年第九届蓝桥杯B组题解

可以先对三个数组排序,然后遍历数组b,查找a数组中有多少个小于b[i]的,c数组中有多少个大于b[i]的。

还有就是可以直接线性求出答案,即a[x]表示第一个序列中,有多少个数字等于x,b[],c[]同理那么有:
for i = 100000 → 0
c[i] = c[i]+c[i+1]
b[i] = b[i]*c[i+1]+b[i+1]
a[i] = a[i]*b[i+1]+a[i+1]

最后a[0]就是答案

二分方法实现代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. const int MAXN = 100005;  
  7. int a[MAXN],b[MAXN],c[MAXN];  
  8. int n,sum;  
  9.   
  10. int main()  
  11. {  
  12.   scanf("%d",&n);  
  13.   for(int i=0;i<n;i++)scanf("%d",&a[i]);  
  14.   for(int i=0;i<n;i++)scanf("%d",&b[i]);  
  15.   for(int i=0;i<n;i++)scanf("%d",&c[i]);  
  16.   sort(a,a+n);  
  17.   sort(b,b+n);  
  18.   sort(c,c+n);  
  19.   sum = 0;  
  20.   for(int i=0;i<n;i++){  
  21.     int x = (lower_bound(a,a+n,b[i]) - a);  
  22.     int y = (n - (upper_bound(c,c+n,b[i]) - c));  
  23.     sum += x*y;  
  24.   }  
  25.   printf("%d\n",sum);  
  26.   return 0;  
  27. }  


第七题:螺旋折线

2018年第九届蓝桥杯B组题解

2018年第九届蓝桥杯B组题解

这道题就把四个象限分一下,然后找规律递推公式就OK了。


第八题:日志统计

2018年第九届蓝桥杯B组题解

这道题就是模拟一下,按id和时间排序,把相同的id,以时间递增的情况排序,然后暴力枚举每个id的赞数,当在规定的时间范围内赞数大于k,标记一下,然后递增输出id就好了。我也不知道我写的对不对,所以就不上代码了。。。


第九题:全球变暖

2018年第九届蓝桥杯B组题解

       这道题应该会有不少人和我一样理解成了最后还剩多少个岛吧。暴力杯变成了阅读理解杯....对于这道题,我们可以用bfs搜索一下把起初的每个岛屿都编上号,顺便把可能会被淹没的岛屿标记下来,然后我是倒着再遍历一遍地图,只要有没有完全淹没的岛屿,就让岛屿数--,最后就剩下完全淹没的岛屿数了。还有一种情况就是有人提到的一个岛屿淹没完以后变成了两个岛屿,那么就在这特判一下就好了。

实现代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <queue>  
  5. using namespace std;  
  6. struct Node{  
  7.   int x,y;  
  8.   int num;  
  9. }Now,Next,S;  
  10. char MAP[1005][1005];  
  11. int vis[1005][1005];  
  12. int dir[4][2] = {1,0,0,1,-1,0,0,-1};  
  13. int n,sum;  
  14.   
  15. bool in(int x,int y){  
  16.   if(x >= 0 && y >= 0 && x < n && y < n)return true;  
  17.   return false;  
  18. }  
  19.   
  20. bool Check(int x,int y){  
  21.   for(int i=0;i<4;i++){  
  22.     int X = x + dir[i][0];  
  23.     int Y = y + dir[i][1];  
  24.     if(MAP[X][Y] == '.' && in(X,Y))return true;  
  25.   }  
  26.   return false;  
  27. }  
  28.   
  29. void bfs(){  
  30.   queue<Node> q;  
  31.   S.num = sum;  
  32.   q.push(S);  
  33.   while(!q.empty()){  
  34.     Now = q.front();  
  35.     q.pop();  
  36.     if(Check(Now.x,Now.y)){  
  37.       vis[Now.x][Now.y] = 1;  
  38.     }  
  39.     for(int i=0;i<4;i++){  
  40.       Next.x = Now.x + dir[i][0];  
  41.       Next.y = Now.y + dir[i][1];  
  42.       if(in(Next.x,Next.y) && MAP[Next.x][Next.y] == '#' && vis[Next.x][Next.y] != 1){  
  43.         if(vis[Next.x][Next.y] == 0)vis[Next.x][Next.y] = 2;  
  44.         Next.num = Now.num;  
  45.         q.push(Next);  
  46.       }  
  47.     }  
  48.   }  
  49.   sum++;  
  50.   return ;  
  51. }  
  52.   
  53. int main()  
  54. {  
  55.   scanf("%d",&n);  
  56.   for(int i=0;i<n;i++){  
  57.     scanf("%s",MAP[i]);  
  58.   }  
  59.   memset(vis,0,sizeof(vis));  
  60.   sum = 0;  
  61.   for(int i=0;i<n;i++){  
  62.     for(int j=0;j<n;j++){  
  63.       if(MAP[i][j] == '#'){  
  64.         if(vis[i][j] != 0)continue;  
  65.         S.x = i;  
  66.         S.y = j;  
  67.         bfs();  
  68.       }  
  69.     }  
  70.   }  
  71.   for(int i=n-1;i>=0;i--){  
  72.     for(int j=n-1;j>=0;j--){  
  73.       if(MAP[i][j] == '#' && vis[i][j] == 2){  
  74.         sum--;  
  75.       }  
  76.     }  
  77.   }  
  78.   printf("%d\n",sum>0?sum:0);  
  79.   return 0;  
  80. }  


第十题:乘积最大

2018年第九届蓝桥杯B组题解


最后一道题我也不会写,当时是随便暴力了一下过了样例就交了,看了一下别人的题解,确实再给我4个小时我也写不出来...

仔细思考你会发现其实最终答案为负数只有两种情况
①k=n,这n个数都是负数并且n是奇数
②k是奇数,并且这n个数都是负数
其它情况下答案一定为正或者0
为什么呢?一个很简单的证明就是如果你结果为负数,那么你一定可以通过少乘一个负数多乘一个正数,或者少乘一个正数多乘一个负数把答案变成正的

然后正数的情况就好办了
一个很完美的方法就是所有负数取绝对值从大到小排序,所有正数从大到小排序
然后暴力负数选多少个,中间取个最大的就行了
但是这样你肯定不能取模,因为取模就错了,然而直接乘会爆long long
熟练的话你可以写个大整数乘法,不过肯定会超时所以要FFT优化乘法
不会FFT怎么办?
还是将所有负数取绝对值从大到小排序,所有正数从大到小排序
然后一个一个取,每次都取当前最大的数
如果最后刚好为整数,那完美直接输出

如果最后为负数就说明你要调整一下,也就是少乘一个负数多乘一个正数,或者少乘一个正数多乘一个负数,这个时候你只要比一下哪个更大就应该ok!


        明年再战...

相关文章: