第三届蓝桥杯java本科解题报告

1.  【结果填空】黄金分割数0.618与美学有重要的关系。舞台上报幕员所站的位置大约就是舞台宽度的0.618处,墙上的画像一般也挂在房间高度的0.618处,甚至股票的波动据说也能找到0.618的影子....
    黄金分割数是个无理数,也就是无法表示为两个整数的比值。0.618只是它的近似值,其真值可以通过对5开方减去1再除以2来获得,我们取它的一个较精确的近似值:0.618034
    有趣的是,一些简单的数列中也会包含这个无理数,这很令数学家震惊!
    1 3 4 7 11 18 29 47 .... 称为“鲁卡斯队列”。它后面的每一个项都是前边两项的和。
    如果观察前后两项的比值,即:1/3,3/4,4/7,7/11,11/18 ... 会发现它越来越接近于黄金分割数!
    你的任务就是计算出从哪一项开始,这个比值四舍五入后已经达到了与0.618034一致的精度。
    请写出该比值。格式是:分子/分母。比如:29/47

    答案写在“解答.txt”中,不要写在这里!

水题,代码如下:

public class Th001 {

	public static void main(String[] args) {
		long[] arr = new long[1000];
		arr[0]=1; arr[1]=3;
		for(int i = 2; i<100; i++)
			arr[i] = arr[i-1]+arr[i-2];//后一项等于前两项的和
		for(int i = 1; i<=100; i++){
			double tem = (1.0*arr[i-1])/arr[i];
			int aa = (int)(tem*1e6+0.5);//考虑到浮点数有误差故四舍五入转化为整数
			if(aa == 618034){
				System.out.println(arr[i-1]+"/"+arr[i]);
				break;
			}
		}
			
	}

}

答案:1364/2207


2.   【结果填空】 有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复...... 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。
    等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船......”
    请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。
    如果有多个可能的答案,请列出所有答案,每个答案占一行。
    格式是:人数,人数,...
    例如,有一种可能是:20,5,4,2,0

    答案写在“解答.txt”中,不要写在这里!

爆破,代码如下:

public class Th002 {

	public static void main(String[] args) {
		
		for(int i = 1; i<=20; i++)//最多有20人的上限
			for(int j = 1; j<i; j++)//每次都有倒下的,故j<i,下同
				for(int l = 1; l<j; l++)
					for(int r = 1; r<l; r++)
						if(j*r*l+i*l*r+i*j*r+i*j*l == i*j*r*l)
							//由船长喝的酒为1/i+1/j+1/l+1/r=1;
							//但是判断时应转化为整数,故等式两边同乘i*j*l*r
							System.out.println(i+","+j+","+l+","+r+",0");
		
	}

}

答案:

12,6,4,2,0
15,10,3,2,0
18,9,3,2,0

20,5,4,2,0

注意输出别漏了最后的0,一开始我就漏了QAQ


3.【结果填空】 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
    大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
    如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个,金刚石和黄金都以木头代替了......但道理是相同的。
    据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日!
    你的任务是精确计算出到底需要移动多少次。
    很明显,如果只有2个圆盘,需要移动3次。
    圆盘数为3,则需要移动7次。
    那么64个呢?

    答案写在“解答.txt”中,不要写在这里!


如图,这个问题很容易找到递推规律解决,假设我们现在要移动n个圆盘到其他柱子上,我们把前面n-1个圆盘看成一个整体,暂时不考虑最下面的圆盘,因为没有影响。所以问题转化为将n-1个圆盘移到一个柱子上(f[n-1]次),然后将最下面的圆盘移到相邻柱子上(1次),最后将那n-1个圆盘移到最大圆盘的柱子上(f[n-1]次)。得到递推等式:f[n]=2*f[n-1]+1;

但是java中用long求第64个刚好溢出,所以先求出第63个再用BigInteger算...

import java.math.BigInteger;

public class Th003 {

	public static void main(String[] args) {
		long[] f = new long[100];
		f[1]=1;f[2]=3;
		for(int i = 3; i<=64; i++)
			f[i]=2*f[i-1]+1;
		String pres =""+ f[63];
		BigInteger b1 = new BigInteger(pres);
		b1 = b1.multiply(BigInteger.valueOf(2)).add(BigInteger.ONE);
		System.out.println(b1);
	}

}

答案:18446744073709551615

4.    【结果填空】某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:
    每位选手需要回答10个问题(其编号为1到10),越后面越有难度。答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错误处理)。
    每位选手都有一个起步的分数为10分。
    某获胜选手最终得分刚好是100分,如果不让你看比赛过程,你能推断出他(她)哪个题目答对了,哪个题目答错了吗?
    如果把答对的记为1,答错的记为0,则10个题目的回答情况可以用仅含有1和0的串来表示。例如:0010110011 就是可能的情况。
    你的任务是算出所有可能情况。每个答案占一行。
    答案写在“解答.txt”中,不要写在这里!

简单dfs+回溯,不过感觉暴力也是可以算出来的

public class Th004 {
	static int[] book = new int[11];//book[i]=1表示第i题答对,否则答错
	public static void main(String[] args) {
		int sum = 10;
		dfs(sum, 1);
		
	}

	static void dfs(int sum, int i){
		//满足条件则输出
		if(i == 11 &&sum == 100){
			for(int k = 1; k<=10; k++)
				if(book[k]>0)
					System.out.print(1);
				else System.out.print(0);
			System.out.println();
			return;
		}
		if(i > 10) return;
		book[i] = 1;
		dfs(2*sum, i+1);//答对则翻倍
		book[i] = 0;//回溯
		dfs(sum-i, i+1);//答错则减去i
			
	}
}

答案:

1011010000
0111010000
0010110011

不知道没按字典序输出算不算对。。考试的时候也许会手动调下字典序哈哈

5.【代码填空】以下的静态方法实现了:把串s中第一个出现的数字的值返回。
如果找不到数字,返回-1
例如:
s = "abc24us43"  则返回2
s = "82445adb5"  则返回8
s = "ab"   则返回-1   
public static int getFirstNum(String s)
{
if(s==null || s.length()==0) return -1;

char c = s.charAt(0);
if(c>='0' && c<='9') return _____________;  //填空

return ___________________;  //填空
}
请分析代码逻辑,并推测划线处的代码。
答案写在 “解答.txt” 文件中
注意:只写划线处应该填的内容,划线前后的内容不要抄写。

题目说的很清晰,对应填上代码:

(1)c-'0' 

(2)getFirstNum(s.substring(1))

6.【代码填空】

    南北朝时,我国数学家祖冲之首先把圆周率值计算到小数点后六位,比欧洲早了1100年!他采用的是称为“割圆法”的算法,实际上已经蕴含着现代微积分的思想。
    如图【1.jpg】所示,圆的内接正六边形周长与圆的周长近似。多边形的边越多,接近的越好!我们从正六边形开始割圆吧。

    如图【2.jpg】所示,从圆心做弦的垂线,可把6边形分割为12边形。该12边形的边长a'的计算方法很容易利用勾股定理给出。之后,再分割为正24边形,....如此循环会越来越接近圆周。

             

    之所以从正六边开始,是因为此时边长与半径相等,便于计算。取半径值为1,开始割圆吧!
    以下代码描述了割圆过程。
    程序先输出了标准圆周率值,紧接着输出了不断分割过程中多边形边数和所对应的圆周率逼近值。
public class B21
{
public static void main(String[] args)
{
System.out.println("标准 " + Math.PI);

double a = 1; 
int n = 6;

for(int i=0; i<10; i++)
{
double b = Math.sqrt(1-(a/2)*(a/2));
a = Math.sqrt((1-b)*(1-b) + (a/2)*(a/2));

n = ______________; //填空

System.out.println(n + "  " + _______________);  // 填空
}
}
}
请分析代码逻辑,并推测划线处的代码。
答案写在 “解答.txt” 文件中
注意:只写划线处应该填的内容,划线前后的内容不要抄写。


其实题目中已经大致说清楚了如何算圆周率,就是先用正多边形的周长替代圆周长,根据圆周长=2*π*r,由于r=1已经固定,因此接下来就是求多边形的周长。图中也给明了正多边形a'的计算公式,也就是周长=n*a';还有个规律,就是并不是所有正多边形都是这可以这样算的,图中举例的是正六边形,所以我们拓展后应该是正12、24、48...边形。每次都是前一次的两倍,此处用到了分割的思想,将一条边分为两条边。于是代码填空处就不难填了。

答案:n*2 n*a/2

以下是运行结果:


7.【代码填空】
    [12,127,85,66,27,34,15,344,156,344,29,47,....]  
    这是某设备测量到的工程数据。
    因工程要求,需要找出最大的5个值。
    一般的想法是对它排序,输出前5个。但当数据较多时,这样做很浪费时间。因为对输出数据以外的数据进行排序并非工程要求,即便是要输出的5个数字,也并不要求按大小顺序,只要找到5个就可以。
    以下的代码采用了另外的思路。考虑如果手里已经抓着5个最大数,再来一个数据怎么办呢?让它和手里的数据比,如果比哪个大,就抢占它的座位,让那个被挤出来的再自己找位子,....
import java.util.*;
public class B23
{
public static List<Integer> max5(List<Integer> lst)
{
if(lst.size()<=5) return lst;

int a = _______________________;  // 填空
List<Integer> b = max5(lst);

for(int i=0; i<b.size(); i++)
{
int t = b.get(i);
if(a>t)
{
__________________;  // 填空
a = t;  
}
}

return b;
}

public static void main(String[] args)
{
List<Integer> lst = new Vector<Integer>();
lst.addAll(Arrays.asList(12,127,85,66,27,34,15,344,156,344,29,47));
System.out.println(max5(lst));
}
}
    请分析代码逻辑,并推测划线处的代码。
    答案写在 “解答.txt” 文件中
    注意:只写划线处应该填的内容,划线前后的内容不要抄写。

我们先分析一下,由于第一个空后存在递归调用,如果该空过后所调用的lst没有任何变化,那么程序就会陷入一个无限递归,最终得到栈溢出的Exception,所以简单分析得知,第一个空是要让lst出现变化而且是递减的变化,不难想到remove()函数。而对于第二个空,考虑到前面有比较判断,因此大致可以猜出来这个空是进行替换,因为涉及到b,所以不难猜出是替换b的第i个元素。另外,代码填空题有个很笨但有时候却很实用的技巧,那就是把你觉得有可能正确的答案填入并不断运行调试。

答案:lst.remove(0)  b.set(i, a)

9.【编程大题】趣味算式

    匪警请拨110,即使手机欠费也可拨通!
    为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练!
    某批警察叔叔正在进行智力训练:
    1 2 3 4 5 6 7 8 9 = 110;
    请看上边的算式,为了使等式成立,需要在数字间填入加号或者减号(可以不填,但不能填入其它符号)。之间没有填入符号的数字组合成一个数,例如:12+34+56+7-8+9 就是一种合格的填法;123+4+5+67-89 是另一个可能的答案。
    请你利用计算机的优势,帮助警察叔叔快速找到所有答案。
    每个答案占一行。形如:
    12+34+56+7-8+9
    123+4+5+67-89
    ......
    已知的两个答案可以输出,但不计分。 
    各个答案的前后顺序不重要。
   注意:
    请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
    请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。  
    相关的工程文件不要拷入。
    请不要使用package语句。    
    源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。

分析:【dfs+字符串处理】我们先将所有可能的算式的排列组合用dfs求出,再判断这个算式的结果是否等于110,这就涉及到字符串操作了。

代码:

public class Main {
	static String[] op={"", "+", "-"};
	static char[] num ={'0','1','2','3','4','5','6','7','8','9'};
	public static void main(String[] args) {

		dfs(0,1, "");
	}

	private static void dfs(int op2, int e, String ss) {
		//递归出口
		if(e == 10){
			if(convertTocal(ss))
				System.out.println(ss);
			return ;
		}
		//下列加到ss尾部操作分别进行,否则会进行算术相加后加到尾部.也可以中间加个""
		ss += op[op2];
		ss += num[e];
		//递归组成所有排列的表达式
		if(e != 9){
			dfs(0, e+1, ss);
			dfs(1, e+1, ss);
			dfs(2, e+1, ss);
		}
		else dfs(0, e+1, ss);
		
	}

	private static boolean convertTocal(String ss) {
		//相当于先取出第一个操作数,然后每次取出一个操作符和一个操作数进行运算 op1(即sum) +/-op2 +/-op3....
		int sum = 0;
		int i = 0;
		while(i<ss.length()){
			if(ss.charAt(i) == '+' || ss.charAt(i) == '-')
				break;
			i++;
		}
		sum = Integer.parseInt(ss.substring(0, i));//取出第一个操作数 
		int j = i;
		while(j<ss.length() && (ss.charAt(j) == '+' || ss.charAt(j) == '-')){
			int num2 = 0;
			String s2 = "";
			int k;
			for(k = j+1; k<ss.length(); k++){
				if(ss.charAt(k) == '+' || ss.charAt(k) == '-')
					break;
				else s2 += ss.charAt(k);
			}
			num2 = Integer.parseInt(s2);
			if(ss.charAt(j) == '+')
				sum += num2;   //将取出的操作数相加
			else sum -= num2;  //将取出的操作数相减
			j = k;    //j=下一个操作符的位置
		}
		if(sum == 110) return true;
		return false;
	}

}

结果:

123+4+5+67-89
123+4-5-6-7-8+9
123-4+5-6-7+8-9
123-4-5+6+7-8-9
12+34+56+7-8+9
12+3+45+67-8-9
12-3+4-5+6+7+89
1+234-56-78+9
1+2+34+5+67-8+9
1-2+3+45-6+78-9

还有2题编程大题由于本人太菜还没解出来。。有待更新TAT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值