自己感觉本届蓝桥杯的题目还是不错的,就是坑点比较多,要认真读题啊!!!
以下题解都是我后来补得……发现自己错了很多。。。如果有代码或结果不对还请指正,多谢~
至于题目可以去2018年蓝桥杯C++、java B组真题下载。
第1题:
题目大意:
2000年的1月1日,是那一年的第1天。那么,2000年的5月4日,是那一年的第几天?
思路:
最快的思路是用excel直接将两个日期做差得出结果,注意结果要 +1. 当然也可以编程求解。
答案:125
第2题:
题目大意:
每个汉字可以用 16*16的矩阵编码显示,给出10个汉字的编码信息,根据汉字意思作答。
思路:
利用移位操作算出二进制数的每一位对应的是 0 还是 1,然后输出即可。为了方便查看,可以将为 0 的换成空格输出。
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
int i,j,k,a,pos,mp[16];
for(i=0;i<10;i++)
{
for(j=0;j<32;j++)
{
scanf("%d",&a);
if(j%2==0)
{
pos=8;
for(k=0;k<8;k++)
{
pos--;
if(a%2==0) mp[pos]=0;
else mp[pos]=1;
a>>=1;
}
for(k=0;k<8;k++)
{
if(mp[k]==0) printf(" ");
else printf("1");
}
}
else
{
pos=16;
for(k=8;k<16;k++)
{
pos--;
if(a%2==0) mp[pos]=0;
else mp[pos]=1;
a>>=1;
}
for(k=8;k<16;k++)
{
if(mp[k]==0) printf(" ");
else printf("1");
}
printf("\n");
}
}
}
int ans=1;
for(i=0;i<9;i++)
{
ans*=9;
printf("ans=%d\n",ans);
}
return 0;
}
答案:387420489 ,注意是 9的 9次方,不是 9*9……
第3题:
题目大意:
给你100个数,问它们乘积结尾 0 的个数。
思路:
可以无脑用 java大数解决。还有种思路是计算每个数因子中 5 的个数,然后求和。
根据算数基本定理(唯一分解定理),每个数都可以分解成若干个质因子相乘的结果。又因为 2*5 =10,一个数的结尾 0 的个数肯定是其质因子分解中 5 的幂次和 2 的幂次的最小值。显然 5 的个数应该小于 2 的个数,故如果数为 5 的倍数,可以求其 5 的因子的幂次。
代码:
#include<stdio.h>
int main()
{
int i,n,ans;
ans=0;
for(i=0;i<100;i++)
{
scanf("%d",&n);
while(n%5==0)
{
n/=5;
ans++;
}
}
printf("%d\n",ans);
return 0;
}
答案:31
第4题:
题目大意:
用 3块手机测试手机的耐摔程度,问采用最佳方法时最小的测试次数。注意只有3块手机,并且如果手机没摔坏可以继续用。
思路:
由于当时没看到只有 3块手机的条件,我直接当成简单的二分题做了……本题不会,略过……
第5题:
题目大意:
代码填空题。代码的作用是求区间第 k 大的数。
思路:
一般代码填空题都是考察递归,我们可以先算得代码正确运行的结果,然后凑这个结果,也方便验证对错。
看上面的代码,第一行是直接返回结果,说明找到了第 k 大的值,且 i-l+1 的位置就是结果。第三行明显是搜索的左区间。现在要补充第二行,第二行明显要搜索右区间,所以前三个参数可以确定了: a, i , r . 然后考虑递归,前 i-l+1 个数都比要找的位置 k 小,所以我们只需要在右区间寻找第 k-(i-l) 小的数即可。
答案: a,i,r,k-i+l
第6题
题目大意:
有三个等长的数组 A、B、C,请你统计有多少个三元组(i, j, k) 满足:
1. 1 <= i, j, k <= N
2. Ai < Bj < Ck
思路:
注意是严格大于。如果没思路可以暴力求解,还是可以得点分的。
由于暴力时间复杂度为 O(n^3) ,会超时,所以我们考虑将前两个数组排序,然后对于 B 中的每个元素二分搜索 A中小于他的数的个数,再对于 C 中的每个元素二分搜索 B中小于他的数的个数。然后求和就是结果,具体看代码。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int a[100010],b[100010],c[100010],num1[100010],num2[100010];
int main()
{
int i,j,n,pos;
LL ans;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++) scanf("%d",&a[i]);
for(i=0;i<n;i++) scanf("%d",&b[i]);
for(i=0;i<n;i++) scanf("%d",&c[i]);
sort(a,a+n);
sort(b,b+n);
for(i=0;i<n;i++)
{
pos=upper_bound(a,a+n,b[i]-1)-a;
num1[i]=pos;
}
ans=0;
for(i=0;i<n;i++)
{
pos=upper_bound(b,b+n,c[i]-1)-b;
for(j=0;j<pos;j++) ans+=num1[j];
}
printf("%lld\n",ans);
}
return 0;
}
第7题:
题目大意:
根据以上螺旋曲线求出到某个点为止曲线的长度。
思路:
这种题最好找规律求解,每个人找的规律也会大不相同。
先只看 x,对于 x>0 和 x<0 两种情况计算螺旋曲线上横、下横、左竖、右竖的长度之和,可以利用等差数列求出前 n 项和。这是当 x 确定时曲线长度确定的部分。不确定的部分就是最左边(x<0时)或最右边(x>0时)竖着的长度。得出表达式后求和即可。
由于当时时间有限,我的代码不能处理 x=0 的情况,这个可以自己推导,以后若有空我会补上。
代码:
#include<stdio.h>
#include<string.h>
typedef long long LL;
int main()
{
LL x,y,ans;
while(~scanf("%lld%lld",&x,&y))
{
if(x==0) ans=0;
else if(x<0)
{
x=-x;
ans=x*x + x*(x-1) + (x-1)*(x-1) + x*(x-1);
ans+=x-1+y;
}
else
{
ans=x*x + x*(x+1) + x*x + x*(x-1);
ans+=x-y;
}
printf("%lld\n",ans);
}
return 0;
}
后面的题就懒得把代码都敲出来了。。。只说下思路吧。
第8题:
题目大意:
现在我们知道某个时间哪篇文章被点赞,求在一定时间段内,点赞数超过某个数量的文章编号。
思路:
我们要先把不同文章不同时间收到的赞给弄到一起,可以用 vector数组解决。然后对一篇文章的点赞时间排序,利用尺取法计算时间段 D 内收获的赞的数量,如果>k,则输出其编号。
第9题:
题目大意:
你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,因为海平面上升会淹没临海的区域(即上下左右至少有一个挨着海的),问有多少岛屿会被完全淹没。
思路:
这个题应该是用 DFS做,先一遍 DFS求出岛屿的个数,然后将临海的区域淹没,再一遍 DFS求出剩余岛屿的个数。
但是注意一点,一个岛屿部分被淹没后可能会形成多个岛屿……建议给每个岛屿编号,然后求编号减少的个数。