本博客所有蓝桥杯相关代码皆有JAVA实现
试题A:高斯日记
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
这里大家只需要注意一个地方就好了,就是高斯出生的那一天是第一天,这个可能会导致大家结果与答案差1哦,因为我就是这样wa了一发
package lan4A_C;
// 出生的第一天算为一天 高斯日记
public class TestA {
static int dx[] = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
static boolean check(int x){
if(x%400 == 0 || (x%4 == 0 && x%100 != 0))
return true;
return false;
}
public static void main(String[] args) {
int y = 1777;
int m = 4;
int d = 30;
for(int i = 1;i <= 8113-1;i++){
d++;
if(m == 2 && check(y)){
if(d > 29){
d = 1;
m++;
}
}
else{
if(d > dx[m]){
d = 1;
m++;
}
}
if(m > 12){
m = 1;
y++;
}
}
System.out.println(y+" "+m+" "+d);
}
}
试题B:排它平方数
小明正看着 203879 这个数字发呆。
原来,203879 * 203879 = 41566646641
这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。
具有这样特点的6位数还有一个,请你找出它!
再归纳一下筛选要求:
1. 6位正整数
2. 每个数位上的数字不同
3. 其平方数的每个数位不含原数字的任何组成数位
答案是一个6位的正整数。
这个题目意思很简单,无非就是要我们枚举6位数判断一下即可
(1)这里我使用get1函数将这个6位数分解在a数组中,方便判断是否与乘积后出现重复。
(2)使用get2函数将乘积后的结果分位存放在b数组中,理由与上面相同,
另外用个变量cnt计数看结果有多少位数
package lan4A_C;
import java.util.*;
public class TestB {
static long a[] = new long[6]; // 存6位数
static long b[] = new long[20];;
static int cnt = 0;
static void get1(long x){
int k = 5;
while(x != 0){
long t = x%10;
a[k] = t;
x /= 10;
k--;
}
}
static void get2(long x){
cnt = 0;
while(x != 0){
long t = x%10;
b[cnt++] = t;
x /= 10;
}
}
public static void main(String[] args) {
for(long i = 100000;i < 1000000;i++){
get1(i);
TreeSet<Long> set = new TreeSet<Long>();
for(int j = 0;j < 6;j++)
set.add(a[j]);
if(set.size() == 6){ // 6位数第不相同
long s = i*i;
get2(s);
int j = 0;
boolean ok = false;
for(j = 0;j < cnt;j++){ // 判断每个数是否重复
int k = 0;
if(ok)
break;
while(k < 6){
if(b[j] == a[k]){
ok = true; // 是否出现了重复
break;
}
k++;
}
}
if(!ok){
System.out.println(i);
}
}
}
}
}
试题C:振兴中华
小明参加了学校的趣味运动会,其中的一个项目是:跳格子。
地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg)
比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。
要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
这个题说实话。。我一看这图片这么小,我还想手算,然后发现结果真的有点多,所以建议还是编程实现以下,结果还真不小。
(1)很简单的dfs思路,我们可以把数组从我做起,振兴中华看成数字12345678存在数组中,然后就好办了
package lan4A_C;
public class TestC {
static int map[][] = new int[][]{
{1,2,3,4,5},
{2,3,4,5,6},
{3,4,5,6,7},
{4,5,6,7,8}
};
static int ans = 0;
static int dx[] = new int[]{1,-1,0,0};
static int dy[] = new int[]{0,0,1,-1};
static void dfs(int x,int y){
if(map[x][y] == 8){
ans ++;
return;
}
for(int i = 0;i < 4;i++){
int xx = x+dx[i];
int yy = y+dy[i];
if(xx>=0&&xx<4&&yy>=0&&yy<5 && map[xx][yy]-map[x][y] == 1)
dfs(xx,yy);
}
}
public static void main(String[] args) {
dfs(0,0);
System.out.println(ans);
}
}
试题D:颠倒的价牌
小李的店里专卖其它店中下架的样品电视机,可称为:样品电视专卖店。
其标价都是4位数字(即千元不等)。
小李为了标价清晰、方便,使用了预制的类似数码管的标价签,只要用颜色笔涂数字就可以了(参见p1.jpg)。
这种价牌有个特点,对一些数字,倒过来看也是合理的数字。如:1 2 5 6 8 9 0 都可以。这样一来,如果牌子挂倒了,有可能完全变成了另一个价格,比如:1958 倒着挂就是:8561,差了几千元啊!!
当然,多数情况不能倒读,比如,1110 就不能倒过来,因为0不能作为开始数字。
有一天,悲剧终于发生了。某个店员不小心把店里的某两个价格牌给挂倒了。并且这两个价格牌的电视机都卖出去了!
庆幸的是价格出入不大,其中一个价牌赔了2百多,另一个价牌却赚了8百多,综合起来,反而多赚了558元。
请根据这些信息计算:赔钱的那个价牌正确的价格应该是多少?
题意就是说有一些数字是可以颠倒的,4个数字放在一起成为一个牌子,如果这个牌子可以颠倒,说明这4个数字都可以颠倒,然后我们根据这个在去判断一下就好了
package lan4A_C;
public class TestD { // 11 22 55 69 88 96 00
static int a[] = new int[]{0,1,2,-1,-1,5,6,-1,8,9}; // 不能颠倒设为-1
static boolean get(int x){ // 是否满足颠倒
while(x != 0){
int t = x%10;
if(a[t] == -1)
return false;
x /= 10;
}
return true;
}
static int last(int x){ // 颠倒后的结果
int sum = 0;
while(x != 0){
sum *= 10;
int t = x%10;
if(t == 6)
sum += 9;
else if(t == 9)
sum += 6;
else
sum += t;
x /= 10;
}
return sum;
}
public static void main(String[] args) {
for(int i = 1000;i < 10000;i++)
for(int j = 1000;j < 10000;j++)
if(get(i) && get(j)){
int t1 = i - last(i);
int t2 = last(j) - j;
if(t1>200 && t1<300 && t2>800 && t2<900 && t2-t1==558){
System.out.println(i+" "+j);
return;
}
}
}
}
试题G:错误票据
某涉密单位下发了某种票据,并要在年终全部收回。
每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
这个题思路很清晰,就是找到没有的编号跟重复的编号即可,很清晰的排序思路。
(1)这个题的读入是给了一个行数,但是没有给每行有多少个数,我们这里可以用每行读入,读入后然后用split函数将每个数字都分开就好了split("\D+")表示将除了数字以外的字符作为分隔符全部去掉,然后存放在String数组中
(2)这个题的数字范围不大于100000,这里我就用计数排序来实现了因为最近刚刚学了计数排序,故想装下B 关于计数排序,如果有不懂的,可以先看下别人的博客- -,我估计几天后也会发,发了会贴在此题下面。
(3)还是简单解释一下,计数排序也称为桶排序,就是把数字的最大范围设为数组的最大上限,然后每读入一个数就把这个数存在相对应的数组下标中,比如读入3,就存在a[3]中,读入98888就存在a[98888]中,次方法只适用于数字不是很大的情况下。
package lan4A_C;
import java.util.*;
public class TestG {
static int a[] = new int[100100];
static int n;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
sc.nextLine();
for(int i = 0;i < n;i++){
String s[] = sc.nextLine().split("\\D+");
for(int j = 0;j < s.length;j++)
a[Integer.valueOf(s[j])]++;
}
int key[] = new int[2]; // 存结果
Arrays.fill(key, 0);
for(int i = 0;i < 100002;i++){
if(a[i] == 0 && i-1>=0 && a[i-1]!=0 && a[i+1]!=0)
key[0] = i;
if(a[i] == 2)
key[1] = i;
if(key[0] != 0 && key[1] != 0)
break;
}
System.out.println(key[0]+" "+key[1]);
}
}
试题H:买不到的数目
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
害- - 这个题真是心累,我就不写回答了,大家看这个大佬的玄学证明过程吧
玄学证明
总是就是结果就是 a*b-a-b
package lan4A_C;
import java.util.*;
public class TestH {
static int a[] = new int[1000000];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
int k = sc.nextInt();
System.out.println(t*k-k-t);
}
}
试题I:剪格子
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
说实话,我真的不认为这个题会给直接使用dfs的代码过,因为dfs只能一个方向搜索,在回溯的时候不可能产出2个方向的区域,但是我刷题的时候还是使用了dfs。。。因为本人太菜,写不出完美代码
上述给出一个例子
5 2 3
6 4 5
8 9 18
这个题题意要的是如果可以分的话,我们要选有左上格子的,那么很明显,我们选出来的可以是5 2 6 8 9 但是dfs不可能搜出来这种结果的。。本人太菜,欢迎大佬指出错误
最后还是发一下代码
package lan4A_C;
import java.io.*;
import java.util.Arrays;
public class TestI {
static int n,m;
static int map[][];
static boolean vis[][];
static int ans = 0;
static int sum = 0;
static int xx[] = new int[]{1,-1,0,0};
static int yy[] = new int[]{0,0,1,-1};
static void dfs(int x,int y,int cnt,int k){
if(cnt == (sum>>1)){
ans = k;
return;
}
if(cnt > (sum>>1))
return;
for(int i = 0;i < 4;i++){
int dx = x + xx[i];
int dy = y + yy[i];
if(dx>=0 && dx<n && dy>=0 && dy<m && !vis[dx][dy]){
vis[dx][dy] = true;
dfs(dx,dy,cnt+map[dx][dy],k+1);
vis[dx][dy] = false;
}
}
}
public static void main(String[] args) throws IOException{
StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
re.nextToken(); m = (int)re.nval;
re.nextToken(); n = (int)re.nval;
map = new int[n][m];
vis = new boolean[n][m];
for(int i = 0;i < n;i++){
Arrays.fill(vis[i], false);
for(int j = 0;j < m;j++){
re.nextToken();
map[i][j] = (int)re.nval;
sum += map[i][j];
}
}
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
for(int k = 0;k < n;k++)
Arrays.fill(vis[k], false);
vis[i][j] = true;
dfs(i,j,map[i][j],1);
if(ans != 0){
pr.println(ans);
pr.flush();
return;
}
}
}
}
}
试题J:大臣的旅费
这个题另外写了一篇博客,大家有需要的可以跳转下网页
大臣的旅费