蓝桥杯省赛12

来源:互联网 发布:分辨率300的软件 编辑:程序博客网 时间:2024/06/06 17:12
一,数量周期

【结果填空】(满分9分)

    复杂现象背后的推动力,可能是极其简单的原理。科学的目标之一就是发现纷繁复杂的自然现象背后的简单法则。爱因斯坦的相对论是这方面的典范例证。

    很早的时候,生物学家观察某区域某种昆虫的数量(称为虫口数)之逐年变化规律,就十分迷惑:有的时候是逐渐增多达到一个平衡值。有的时候在两个数字间周期跳动。有的时候则进入一片混乱,类似随机数字一样变化(称为混沌现象)。

    慢慢地,人们从数学中更清晰地观察到了这一现象,并因此开创了:符号动力学、非线性动力学等研究领域。

    一个著名的虫口数目简化模型如下:

    x' = x * (1 - x) * r

    这里,x  x' r 都是浮点数。
 
    其中,x 表示当年的虫口数,x' 表示下一年的虫口数。它们的取值范围在 0 与 1 之间,实际上表示的是:虫口的总数占环境所能支持的最大数量的比率。

    r 是常数(环境参数),r的取值范围在 [0,4]。

    令人惊讶的是:这个简单的迭代公式有着不同寻常的神秘性质!

    一般来说,多次迭代后,虫口数的稳定模式与x的初始值无关,而与 r 有关!

    例如:无论x初始值是多少,当 r = 2.5 的时候,x 多次迭代后会趋向于 0.6。

    而当 r = 3.2 的时候,x 的值会趋向于在 0.799 与 0.513 之间周期性摆动。

    那么,r = 3.62 的时候,你观察到有什么周期现象发生吗?

0.5-0.8

    不需要提交源代码,只要写出你的结论即可!

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

public class test2 {public static float getX(int n){if(1==n)return (float)0.5;elsereturn (float)(getX(n-1)*(1 - getX(n-1)) * 3.62f);}public static void main(String[] args) {for(int i=1;i<100;i++){System.out.println(getX(i));}}}

2,
    黄金分割数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”中,不要写在这里!

1364.0/2207.0
public class test1 {static String s ="";public static int queue(int n){if(1==n)return 1;else if(2==n)return 3;elsereturn queue(n-1)+queue(n-2);}public static void yes(float x,float y){//System.out.println(String.format("%.2f",((m2-m1)*(n2-n1))));if(String.format("%.6f", x/y).equals("0.618034"))s=""+x+"/"+y;}public static void main(String[] args) {for(int i=1;i<1000;i++){yes(queue(i),queue(i+1));System.out.println(s);}}/*1364.0/2207.02207.0/3571.03571.0/5778.0*/}

二,提取子串

【代码填空】(满分12分)
    
    串“abcba”以字母“c”为中心左右对称;串“abba” 是另一种模式的左右对称。这两种情况我们都称这个串是镜像串。特别地,只含有1个字母的串,可以看成是第一种模式的镜像串。 

    一个串可以含有许多镜像子串。我们的目标是求一个串的最大镜像子串(最长的镜像子串),如果有多个最大镜像子串,对称中心靠左的优先选中。例如:“abcdeefghhgfeiieje444k444lmn”的最大镜像子串是:“efghhgfe”

    下面的静态方法实现了该功能,请仔细阅读并分析代码,填写空白处的代码,使得程序的逻辑合理,结果正确。

// 求最大(长度最大)镜像对称子串

public class test2_b {// 求最大(长度最大)镜像对称子串public static String getMaxMirrorString(String s){String max_s = "";  // 所求的最大对称子串for(int i=0; i<s.length(); i++){// 第一种对称模式int step = 1;try{for(;;){if(s.charAt(i-step) != s.charAt(i+step)) break;step++;}}catch(Exception e){}String s1 = s.substring(i-step+1,i+step);     // 填空1// 第二种对称模式step = 0;try{for(;;){if(s.charAt(i-step) != s.charAt(i+step+1)) break;    // 填空2step++;}}catch(Exception e){}String s2 = s.substring(i-step+1,i+step+1);if(s1.length() > max_s.length()) max_s = s1;if(s2.length() > max_s.length()) max_s = s2;}return max_s;}public static void main(String[] args) {String s = "abcdeefghhgfeiieje444k444lmn";System.out.println(getMaxMirrorString(s));//System.out.println(s.charAt(-1));}}

    有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复...... 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。

    等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船......”

    请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。

    如果有多个可能的答案,请列出所有答案,每个答案占一行。

    格式是:人数,人数,...

    例如,有一种可能是:20,5,4,2,0

    答案写在“解答.txt”中,不要写在这里!
12 6 4 2 0
15 10 3 2 0
18 9 3 2 0
20 5 4 2 0

public class test_2_a {public static void main(String[] args) {int sum =0;for(int a=4;a<=20;a++)for(int b=3;b<=19;b++)for(int c=2;c<=18;c++)for(int d=2;d<=17;d++)if(a>b && b>c && c>d){if(((b*c*d+a*c*d+a*b*d+a*b*c)==(a*b*c*d))){System.out.println(a+" "+b+" "+c+" "+d+" "+0);sum++;}}System.out.println(sum);}}


三,汉诺塔
    汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
    大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

    如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个,金刚石和黄金都以木头代替了......但道理是相同的。

    据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日!

    你的任务是精确计算出到底需要移动多少次。

    很明显,如果只有2个圆盘,需要移动3次。

    圆盘数为3,则需要移动7次。

    那么64个呢?

//超时

public class test3_a{static int source=6;//初始值static String start="start";//开始,临时,最后static String temp="temp";static String end="end";static int sum=0;public static void hanio(int source,Object start,Object temp,Object end){if(source==1)move(1,start,end);else{//一次完整的从start移动到endhanio(source-1,start,end,temp);//把n-1从start 借助end 移动到tempmove(source, start, end);//输出移动start到endhanio(source-1, temp, start, end);//把n-2从temp 借助start 移动到end}}private static void move(int source,Object start,Object end) {System.out.println("move--"+source+"----from----"+start+"----to----"+end);sum++;}public static void main(String[] args) {hanio(source,start,temp,end);System.out.println(sum);}}


四,奇怪的比赛

    某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:

    每位选手需要回答10个问题(其编号为1到10),越后面越有难度。答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错误处理)。

    每位选手都有一个起步的分数为10分。

    某获胜选手最终得分刚好是100分,如果不让你看比赛过程,你能推断出他(她)哪个题目答对了,哪个题目答错了吗?

    如果把答对的记为1,答错的记为0,则10个题目的回答情况可以用仅含有1和0的串来表示。例如:0010110011 就是可能的情况。

    你的任务是算出所有可能情况。每个答案占一行。

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

public class test4_a_a {public static void fun(int[] a,int num,int grade){if(num>10){if(grade==100){for(int i=1;i<=10;i++)System.out.print(""+a[i]);System.out.println("");//return;}}else{a[num]=0;fun(a,num+1,grade-num);a[num]=1;fun(a,num+1,grade*2);}}public static void main(String[] args) {int[] a = new int[11];//题的正确与错误fun(a,1,10);}}

类型题

输入一个正整数m,输出m位2进制的所有取值情况,从小到大输出,每个输出结果用换行符分割。

import java.util.Scanner;//输入一个正整数m,输出m位2进制的所有取值情况,从小到大输出,每个输出结果用换行符分割。public class test4_a_b {//通过递归调用,从第1个到第m个数组元素分别置0和置1,然后当从1到m所有的元素都置0或者置1之后,进行输出。public static void fun(int[] a,int num,int m){if(num>m){for(int i=1;i<=m;i++){System.out.print(""+a[i]);}System.out.println("");}else{a[num]=0;fun(a,num+1,m);a[num]=1;fun(a,num+1,m);}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int[] a = new int[m+1];fun(a,1,m);}}

【编程题】(满分23分)

    俗话说:十赌九输。因为大多数赌局的背后都藏有阴谋。不过也不尽然,有些赌局背后藏有的是:“阳谋”。

    有一种赌局是这样的:桌子上放六个匣子,编号是1至6。多位参与者(以下称玩家)可以把任意数量的钱押在某个编号的匣子上。所有玩家都下注后,庄家同时掷出3个骰子(骰子上的数字都是1至6)。输赢规则如下:

    1. 若某一个骰子上的数字与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目赔付(即1比1的赔率)。

    2. 若有两个骰子上的数字与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目的2倍赔付(即1比2的赔率)。

    3. 若三个骰子上的数字都与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目的6倍赔付(即1比6的赔率)。

    4 若玩家所押注匣子号与某个骰子示数乘积等于另外两个骰子示数的乘积,则玩家拿回自己的押注,庄家也不赔付(流局)。

    5. 若以上规则有同时满足者,玩家可以选择对自己最有利的规则。规则执行后,则庄家收获所有匣子上剩余的押注。

    乍一看起来,好像规则对玩家有利,庄家吃亏。但经过大量实战,会发现局面很难说,于是怀疑是否庄家做了手脚,庄家则十分爽快地说:可以由玩家提供骰子,甚至也可以由玩家来投掷骰子。

    你的任务是:通过编程模拟该过程。模拟50万次,假定只有1个玩家,他每次的押注都是1元钱,其押注的匣子号是随机的。再假定庄家有足够的资金用于赔付。最后计算出庄家的盈率(庄家盈利金额/押注总金额)。

【输入、输出格式要求】

    程序无输入,程序运行输出庄家的盈率,四舍五入保留到小数后3位。


public class test4_a {static int sum = 0;public static int test(){int p_num = (int) (Math.random()*6+1);int s_num1 = (int) (Math.random()*6+1);int s_num2 = (int) (Math.random()*6+1);int s_num3 = (int) (Math.random()*6+1);if(p_num==s_num1 && p_num==s_num2 && p_num==s_num3){return -6;}else if((p_num==s_num1 && p_num==s_num2 && p_num!=s_num3)||(p_num==s_num2 && p_num==s_num3 && p_num!=s_num1)||(p_num==s_num3 && p_num==s_num1 && p_num!=s_num2)){return -2;}else if((p_num==s_num1 &&p_num!=s_num2&&p_num!=s_num3)||(p_num==s_num2 &&p_num!=s_num1&&p_num!=s_num3)|| (p_num==s_num3 &&p_num!=s_num2&&p_num!=s_num1)){return -1;}else if((p_num*s_num1==s_num2*s_num3) || (p_num*s_num2==s_num1*s_num3) ||(p_num*s_num3==s_num2*s_num1)){return 0;}elsereturn 1;}public static void main(String[] args) {for(int i=1;i<=500000;i++){sum+=test();}System.out.println(String.format("%.3f", sum/500000.0));//System.out.println(sum);}}


五,第一个数字

以下的静态方法实现了:把串s中第一个出现的数字的值返回。
如果找不到数字,返回-1

例如:
s = "abc24us43"  则返回2
s = "82445adb5"  则返回8
s = "ab"   则返回-1   

public class test5_a {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 c-48;  //填空return getFirstNum(s.substring(1));  //填空}public static void main(String[] args) {String s ;//s = "abc24us43"; // 则返回2 50s = "82445adb5"; // 则返回8 56//s = "ab";   //则返回-1   System.out.println(getFirstNum(s));}}

六, 割圆


    南北朝时,我国数学家祖冲之首先把圆周率值计算到小数点后六位,比欧洲早了1100年!他采用的是称为“割圆法”的算法,实际上已经蕴含着现代微积分的思想。

    如图【1.jpg】所示,圆的内接正六边形周长与圆的周长近似。多边形的边越多,接近的越好!我们从正六边形开始割圆吧。

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

    之所以从正六边开始,是因为此时边长与半径相等,便于计算。取半径值为1,开始割圆吧!

    以下代码描述了割圆过程。
    
    程序先输出了标准圆周率值,紧接着输出了不断分割过程中多边形边数和所对应的圆周率逼近值。


                     



 
public class test6_a {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 = 2*n; //填空System.out.println(n + "  " +n*a/2.0 );  // 填空}}}


七,最大数


    [12,127,85,66,27,34,15,344,156,344,29,47,....]  

    这是某设备测量到的工程数据。

    因工程要求,需要找出最大的5个值。

    一般的想法是对它排序,输出前5个。但当数据较多时,这样做很浪费时间。因为对输出数据以外的数据进行排序并非工程要求,即便是要输出的5个数字,也并不要求按大小顺序,只要找到5个就可以。

    以下的代码采用了另外的思路。考虑如果手里已经抓着5个最大数,再来一个数据怎么办呢?让它和手里的数据比,如果比哪个大,就抢占它的座位,让那个被挤出来的再自己找位子,....

import java.util.Arrays;import java.util.List;import java.util.Vector;public class test7_a {public static List<Integer> max5(List<Integer> lst){if(lst.size()<=5) return lst;int a = lst.remove(lst.size()-1);  // 填空List<Integer> b = max5(lst);for(int i=0; i<b.size(); i++){int t = b.get(i);if(a>t){b.set(i, a);  // 填空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));}}

九,

    匪警请拨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
......

    已知的两个答案可以输出,但不计分。

public class test9 {public static void fun(String str,int num){if(num==9)check(str);else{fun(str.replace(num+"", num+"+"),num+1);fun(str.replace(num+"", num+"-"),num+1);fun(str,num+1);}}private static void check(String str) {String[] ss1 = str.split("\\+");int sum=0;for(String s : ss1){String[] ss2 = s.split("\\-");int res = Integer.parseInt(ss2[0]);for(int i=1;i<ss2.length;i++)res-=Integer.parseInt(ss2[i]);sum+=res;}if(sum==110)System.out.println(str);}public static void main(String[] args) {//123+4+5+67-89=110  123 4 5 67-89  67 89fun("123456789",1);}}


0 0