2014年省赛题

题目列表:

  1. 猜年龄
  2. 等额本金
  3. 猜字母
  4. 大衍(yan)数列
  5. 写日志
  6. 李白打酒
  7. 奇怪的等式
  8. 兰顿蚂蚁
  9. 地宫取宝
  10. 矩阵翻硬币(未做)

一、猜年龄

答案:10
思路:
注意题目中的“我们俩的年龄之积是年龄之和的6倍”,凭借这句话可以得到等式:i * j == (i+j)*6。
我们可以设年龄小的那个女人在1到100之间,年龄大的在年龄小的基础上增加,上界小于等于8(她们可不是双胞胎,年龄差肯定也不超过8岁啊)。
最后我们直接打印,然后发现会有两组答案,这时我们可以看到小明说的:她们可不是双胞胎,年龄差肯定也不超过8岁啊。得到第一组答案,然后根据题目要求:上交10即可。

import java.util.Scanner;
public class T1GuessAge {
 public static void main(String[] args){
  Scanner sc = new Scanner(System.in);
  /*
   * 题目:猜年龄:
   * 小明带两个妹妹参加元宵灯会。别人问她们多大了,她们调皮地说:
   * “我们俩的年龄之积是年龄之和的6倍”。
   * 小明又补充说:“她们可不是双胞胎,年龄差肯定也不超过8岁啊。”
   * 
   * 请你写出:小明的较小的妹妹的年龄。
   * 注意: 只写一个人的年龄数字,请通过浏览器提交答案。不要书写任何多余的内容。
   * 
   * answer: 10 15
   */
  for(int i = 1; i < 100; i++){
   for(int j = i; j < i+8; j++){
    if(i*j == (i+j)*6){
     System.out.println(i+" "+j);
    }
   }
  }
  
 
 }
}

二、等额本金

答案:1312.50
这题是一个简单的数学题,我花了几分钟做完后,感觉有坑,后来发现答案就是我算的那个,所以说这题很水!值得注意的是,上交的时候要保留小数点后两位……

import java.util.Scanner;
public class T2DengErBanJIng {
 public static void main(String[] args){
  Scanner sc = new Scanner(System.in);
  /*
   * 小明从银行贷款3万元。约定分24个月,以等额本金方式还款。
   * 这种还款方式就是把贷款额度等分到24个月。
   * 每个月除了要还固定的本金外,还要还贷款余额在一个月中产生的利息。
   * 
   * 假设月利率是:0.005,即:千分之五。那么,
   * 第一个月,小明要还本金 1250, 还要还利息:30000 * 0.005,总计 1400
   * 第二个月,本金仍然要还 1250, 但利息为:(30000-1250) * 0.005 总计 1393.75
   * 
   * 请问:小明在第15个月,应该还款多少(本金和利息的总和)?
   * 请把答案金额四舍五入后,保留两位小数。注意:32.5,一定要写为:32.50
   * 
   * 通过浏览器提交答案,这是一个含有小数点和两位小数的浮点数字。不要写多余内容
   * (例如:多写了“元”或添加说明文字)
   * 
   * answer:1312.50
   */
  
  double rate = 0.005;
  double balance = 1250;
  double result = 0;
  
  for(int i = 1; i < 16; i++){
   result = (30000-balance*(i-1)) * rate + balance;
  }
  
  System.out.println(String.format("%.2f",result));
 }
}

三、猜字母

答案:q
这题我是常规操作,当我看完题目,发现了一个问题(突破点):循环删除奇数位置上的字母,这时我想到了递归,本来我的递归不怎么好,所以也是抱着尝试的心里去做,后来做着做着突然打印出一个字母,别提我的心有多激动了。这也侧面证明用递归做,不难!!我写递归的时候,首先写的是出口,也就是:if(str.length() == 1)return str;因为我知道题目要求一个字符,所以递归的边界一定是字符串长度等于0时结束。接下来我把2014个19个字母组成的字符串转换为字符数组,如果遇到偶数位,则continue,否则就加载一个空字符串中,以此类推(你懂的)……
对于题目的第一句相信聪明的你是没有问题的(暗示看代码)
上代码:

public class T3GuessWord {
 public static void main(String[] args){
  /*
   * 把abcd...s共19个字母组成的序列重复拼接106次,得到长度为2014的串。
   * 接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字母。
   * 得到的新串再进行删除奇数位置字母的动作。如此下去,最后只剩下一个字母,请写出该字母。
   * 
   * 答案是一个小写字母,请通过浏览器提交答案。不要填写任何多余的内容。
   * 
   * answer:q
   */
  
  String s1 = "abcdefghijklmnopqrs";
  String s2 = "";
  for(int i = 1; i <= 106; i++){
   s2 += s1;
  }
  //System.out.println(s2);
  
  System.out.println(f(s2));
 }
  
 
 static String f(String s){
  String str = s;
  if(str.length() == 1){
   return str;
  }
  
  char[]arr = s.toCharArray();
  String s1 = "";
  for(int i = 0; i < s.length(); i++){
   if(i % 2 == 0){
    continue;
   }else{
    s1 += arr[i];
   }
  }
  
  return f(s1);
 }
 }

四、大衍数列

答案:answer:i % 2 == 0
上代码:

public class T4DaYanShuLiang {
 public static void main(String[] args){
  /*
   * 中国古代文献中,曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。
      它的前几项是:0、2、4、8、12、18、24、32、40、50 ...
       其规律是:对偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。
       以下的代码打印出了大衍数列的前 100 项。
   for(int i=1; i<100; i++)
      {
   if()
       if(________________)  //填空
           System.out.println(i*i/2);
       else
           System.out.println((i*i-1)/2);
   }
      
       请填写划线部分缺失的代码。通过浏览器提交答案。
   注意:不要填写题面已有的内容,也不要填写任何说明、解释文字。
   answer:i % 2 == 0
      */
      }
      }

五、写日志

答案:n<=3?n++:1
思路:
看完题目后,我第一反应是n++;第二反应是使用if条件判断,如果n超过3,则n=1;第三反应,这是填空题,只能填写一行代码;第四反应:使用boolean表达式
就这样答案就出来了。
后来我看了微课,发现标准答案就是标准答案,他的答案是:n%3+1
对于这个答案我就还是那两个字:真牛逼!
不够我有了一个新的心得
在做填空题的时候,最好不要填完了就直接下一题,自己填完了后最好在验证一下,虽然会损失一两分钟,但是如果因为粗心导致整个题都错了,相信考完后你的心情会很丰富多彩的

上代码:

public class T5WriteDiary {
 public static void main(String[] args){
 /*
  * 写日志是程序的常见任务。
  * 现在要求在 t1.log, t2.log, t3.log 三个文件间轮流写入日志。
  * 也就是说第一次写入t1.log,第二次写入t2.log,... 第四次仍然写入t1.log,如此反复。
     下面的代码模拟了这种轮流写入不同日志文件的逻辑。
  public class A
  {
      private static int n = 1;
      public static void write(String msg)
      {
          String filename = "t" + n + ".log";
          n = ____________;
          n = n<=3?n++:1
          n = n+1;
          if(n > 3){
           n = 1;
          }
                    
          System.out.println("write to file: " + filename + " " + msg);
      }
  }
    answer:n<=3?n++:1
  */
  String s = "!";
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
  write(s);
 }
  
     static int n = 1;
     
     public static void write(String msg)
     {
         String filename = "t" + n + ".log";
         n = n<=3?n++:1;
         n = n+1;
         if(n > 3){
          n = 1;
         }
         
         System.out.println("write to file: " + filename + " " + msg);
         }
         }

好了今晚就到这里吧,我也就做出了这几道题,之后的题目有点难。明天见,真题!

六、李白打酒

answr:14
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。
则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?
请你计算出所有可能方案的个数(包含题目给出的)。
注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。

思路
先说一下题目意思:酒壶里的有2斗酒;遇到店,酒壶里的酒就会加倍(也就是乘2),一共遇店5次;
遇到花,酒壶里的酒就会减一斗(也就是减1),且最后一次遇到的也是花,所以倒数第二次酒壶里还剩下一斗酒啦
把题目理清后,在想方法……
因为最后一次遇到的一定是花,所以可以设李白一共需要走过14个点,且每次过一个点就得考虑是遇到花呢(-1),还是遇到店呢(*2),但无论如何,最后一个点过后,酒壶里还剩下一斗酒。
对于中没走一步就需要考虑两种(或则以上)的情况的题目,类似上楼梯,所以我想到了用递归来做,这样就可以考虑到所有可能出现的情况了。
请看代码……

代码块

public class T6LiBaiDaJiu_one {
 public static void main(String[] args){
  f(9,5,2);
  System.out.println(ans);
 }
 
 static int ans;
 static void f(int hua, int dian, int jiu){
  if(hua == 0 && dian == 0 && jiu == 1){
   ans++;
  }
  if(hua>0)f(hua-1,dian,jiu-1);
  if(dian>0)f(hua,dian-1,jiu*2);
 }
 }

七、奇怪的等式

答案:14
感想
这题注意审题要认真,别想我一样,等我做完了这道题,发现自己的答案和题目描述的严重不符,可是我验证的时候又是对的,这让我以为是不是题目错了?,后来才发现我看题的时候漏了条件,这也直接导致我多花了20多分钟的时间花在验证上,如果我的运气有点背的话,可能我就不是多花时间那么简单了,而是直接失去一个简单题目的分数,所以说看题需仔细啊,young man!!!
思路
先看题目的条件有哪些吧:
1、两个分数相乘等于两个分数拼合后的结果
2,分子、分母的范围都是1~9之间的整数
3,分子不等于分母!!!(这个条件在我这里值20多分钟)
通过分析可以得出
我们要想得出答案,就必须考虑的每个分子(分母)都可能是1~9之间的任何一个数字,这就像我们经常说的枚举法(把所以情况一个一个的列出来,然后再用if条件判断,得出答案)
有题目可以得出我们需要四个变量,分别是:两个分子和两个分母。所以我们定义一个四层的for循环,这样我们就可以考虑到1~9之间的每种情况了,在最里层循环,我们设置一个if条件判断,如果前两个分数相乘等于两个分数拼合的值,那么count++(count变量用于存储符合题目条件的次数)
那么如何判断前两个分数相乘等于两个分数拼合的值呢?其实很简单!!(分成等于号前的式子和等于号后的式子)
1,我们先看两个分数相乘这个式子(等于号前的式子):
因为两个分数相乘后可以得到一个分数,所以我们可以将等于号前后的式子都进行同分,然后判断同分后的分子是否相等,如果相等则返回true,否则返回false。
思路知道后我们就可以敲代码了,其中对于判断两式相等的情况我们可以另外定义一个返回值为boolean类型的有参有返回值的方法,这样可以让代码看起来比较“爽”。
字不多写,上代码:

代码块

public class T7QiGuaiDeFenShi {
	public static void main(String[] args){
		
		int count = 0;
		for(int a = 1; a <= 9; a++){
			for(int b = 1; b <= 9; b++){
				for(int c = 1; c <= 9; c++){
					for(int d = 1; d <= 9; d++){
						
						if(tf(a,b,c,d)){
							System.out.println(a+" "+b+" "+c+" "+d);
							count++;
						}
						
					}
				}
			}
		}
		
		System.out.println(count);
	}
	
	static boolean tf(int a, int b, int c, int d){
		//表达式一:a/b和c/d
		int m = a*c;//分子
		int n = b*d;//分母
		
		//表达式二:ac/bd
		int k = a*10+c;//分子
		int p = b*10+d;//分母
		
		//表达式一和表达式二同分
		int zi1 = m*p;//前一个分子
		int zi2 = k*n;//后一个分子
		int mu = p*n;//公共的分母
		
		//当两边的式子分母相同时,分子相等就返回true,否则返回false
		if(zi1 == zi2 && zi1 != mu && zi2 != mu){
			return true;
		}else{
			return false;
		}
	}
	/*81+14
	 * 
1 2 5 4
1 4 8 5
1 6 4 3
1 6 6 4
1 9 9 5

2 1 4 5
2 6 6 5

4 1 5 8
4 9 9 8

6 1 3 4
6 1 4 6
6 2 5 6

9 1 5 9
9 4 8 9
	 */
}

你可以注意到上面个代码的最后的注释是我自己罗列的每种情况,我就是没有看到题目的要求三,导致我解这道题花了20多分钟的时间(偷偷的抹了一把泪)

八、兰顿蚂蚁

思路
这道题的题目要求不多,情况也相对较少,总体难度不算太大,如果你认为我是自己夸自己,那么你就错了……
先看看该题的要求:
1、若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
2、若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。
3、用户输入m n x y s k
m n表示这是一个m*n的矩阵;x y:表示蚂蚁当前的坐标;
s:表示蚂蚁的头的方向;k:表示蚂蚁走的步数
4,白格用0表示,黑格用1表示
是的题目那么长,有用的就只有这两句话。
思路
分析题目要求,可以得出:
1,蚂蚁在黑格时,会右转90度(顺时针);蚂蚁在白格时,会左转90度(逆时针)。所以我们可以把用户输入的蚂蚁头的朝向转化为数字1 2 3 4(分别表示上 右下 左,也就是顺时针方向),这样我们在更新蚂蚁朝向的时候,操作起来会比较容易。比如:上顺时针转90度,就是右,也就是1加1等于2;逆时针的变化规则类似。
2,我们可以定义一个变量step,用于存储蚂蚁每次走的步数,如果step==k,那么此时蚂蚁的位置就是我们需要的答案
3,因为不知道蚂蚁的步数是多少,我们可以使用while循环(通常循环次数不明,就是用while循环)跳出循环条件就是step ==k
4,因为蚂蚁白格和在黑格的走法不同,所以每次走一步分两种情况,一种是在白格时怎么走?一种是在黑格时怎么走?每走完一步step++
当蚂蚁在白格的时候:
先将蚂蚁所在的白格变为黑格,然后判断蚂蚁的朝向,判断朝向后对对应位置进行变动(如蚂蚁头朝上,那么就是蚂蚁所在的坐标轴y加一,x不变。因为蚂蚁在黑格需要右转进一,所以蚂蚁的纵坐标也会进一,而行坐标x不变),然后在变化方向……
当蚂蚁在黑格的时候:走法和蚂蚁在白格的类似

上代码

import java.util.Scanner;
public class T8LanDunMaYii {
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		
		int m = sc.nextInt();
		int n = sc.nextInt();
		int[][]arr = new int[m][n];
		for(int i = 0; i < m; i++){
			for(int j = 0; j < n; j++){
				arr[i][j] = sc.nextInt();
			}
		}
		int x = sc.nextInt();
		int y = sc.nextInt();
		String s = sc.next();
		int d = f(s);
		int k = sc.nextInt();
		
		
		int step = 0;
		while(true){
			//若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
			
			if(arr[x][y] == 1){
				arr[x][y] = 0;
				if(d == 1){
					y += 1;
				}else if(d == 2){
					x += 1;
				}else if(d == 3){
					y -= 1;
				}else if(d == 4){
					x -= 1;
				}
				d = d%4+1;
			//若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。
			}else if(arr[x][y] == 0){
				arr[x][y] = 1;
				if(d == 1){
					y -= 1;
				}else if(d == 2){
					x -= 1;
				}else if(d == 3){
					y +=1;
				}else if(d == 4){
					x += 1;
				}
				
				d--;
				if(d == 0){
					d = 4;
				}
			}
			//System.out.println(arr[x][y]+" "+x+" "+y);
			step++;
			if(step == k){
				break;
			}
		}
		
		System.out.println(x+" "+y);
	}
	
	
	static int f(String s){
		if(s.equals("U"))return 1;
		if(s.equals("R"))return 2;
		if(s.equals("D"))return 3;
		if(s.equals("L"))return 4;
		return 0;
	}
}

总结:相信你看懂了我写的思路或者代码或者自己想明白了后,会说一句:这题原来如此啊,妙哉!妙哉!这题做出来后思路比较简单,代码也不是需要写太多,主要是注意做题的思路以及细节即可……

九、地宫取宝

这题有点难,如果使用我写的第一种做法,那么你会惊奇的发现:我特么怎么才60分。然后发现超时了……
这题提议比较容易理解,可是每走一步所面临的情况却是很多。比如:当你走下一步的时候,你需要考虑我是走右边呢?还是走下边呢?我走到了下一个存放宝物的格子处时,你又得考虑我是取这个宝物呢?还是不取这个宝物?(当然前提是这个宝物的价值比手里上的所有宝物的价格都大),也就是所每走一步就必须面临着四种情况。
思路:
这题和上上上题(李白打酒)类似,只不过情况变复杂了而已。所以我们可以参照李白打酒这题的思路来做,做了之后就不难了……
首先看题目要求:
1、地宫宝库是一个n*m个格子的矩阵,每个格子上有一个宝物
2、每个格子上的宝物用这个宝物的价值来显示,且每个宝物的价值范围是在[0, 12]之间的。
3,当小明从地宫走出后,手里的宝贝恰好是k件
4,对求出的行动方案数对1000000007取模

会做上上上题目的同学因为知道这题得用递归来做,那么每次递归后需要变化的量是什么呢?递归体又是什么呢?出口又是什么?知道了这三个问题,此题不难了!

1,首先我们来想一想递归后需要变化的量是什么?

1)小明不管有没有取宝物,他都会走一格,所以可以确定小明的位置坐标x y一定会变;
2)如果小明要取宝物,那么去宝物的条件是:这个被取得宝物得价值一定是一个最大值,也就是所每次去玩宝物后,都会更新这个所谓得最大值,所以变化得量需要一个最大值来判断宝物是否可取。
3)我们如何判断小明在走出地宫出口之前,手上得宝物一定就是k呢,所以我们又得定义一个会变化得量用于更新小明手中得宝物数量是多少。

2,接下来我们来判断出口和递归体是什么吧:

1)首先判断x 是否等于n,y是否等于m,宝物数量bao是否大于k,如果都是的话,后面的语句也不用执行了,直接返回一个0就可以了(x,y表示小明当前的坐标,对于为什么返回0和1,后面再解释)
2)判断当前宝物的价值是否大于小明手中所有宝物的价值,如果是,则更新最大值。这里需要注意一下,小明也可以遇到价值大的宝物而不取,所以在判断小明是往下走还是往右走的同时还得判断小明取宝物和不取宝物的情况(一共4种情况)
3)判断小明在最后一个格子上手中的宝物是否达到了k个,如果达到了,那么直接返回1;如果没有达到,则最后一个宝物的价值一定大于小明手中所有宝物的价值,然后再return 1
4)为什么要return 1 或者return 0 呢?
我们可以在递归方法中的判断最大值部分下面有:ans+=……这部分正是对return 的0和1进行相加,至于为为什么相加,你懂的……

思路已经说明了(我认为),如果还没看到我写的天书的同志,看代码,我写的代码从来就没有难的
上代码

import java.util.Scanner;
public class T9DiGonQuBao {
	static int n,m,k=0;
	static int[][]arr;
	static final long MOD = 1000000007;
	//他有多少种不同的行动方案能获得这k件宝贝
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		
		//接收用户输入的数据
		n = sc.nextInt();
		m = sc.nextInt();
		k = sc.nextInt();
		arr = new int[n][m];
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				arr[i][j] = sc.nextInt();
			}
		}
		
		//分别表示:x轴  y轴  宝物价格  宝物数量
		long ans = f(0,0,-1,0);
		
		//打印运算结果
		System.out.println(ans);
	}
	
	
	static long f(int x, int y, int max, int bao){
		//如果x or y equals n or m, then arrayoutbound,宝物数量bao不可能大于k,返回并结束0
		if(x == n || y == m || bao > k)return 0;
		
		//假设小明当前位置的宝物价格是temp
		int temp = arr[x][y];
		//令ans表示行动方案的种数
		int ans = 0;
		
		
		
		//如果当前宝物的价格大于最大的价格,那么最大的价格更新为当前价格
		if(temp > max){
			//小明每次走一步,都会面临向右和向下两种选择:
			//1,假设遇到更贵的宝物直接拿走,ans+1
			ans += f(x, y+1, temp, bao+1);
			ans += f(x+1, y, temp, bao+1);
		}
		//2,假设不管遇没遇到更贵的宝物,都不拿走,即ans+0
		ans += f(x, y+1, max, bao);
		ans += f(x+1, y, max, bao);
		
		//如果小明在最后一个格子上
		if(x == n-1 && y == m-1){
			//如果此时的宝物数量等于k,或者宝物数量等于k-1且宝物价格比手上的任何一个宝物的价格都贵,那么就返回1
			if(bao == k || (bao == k-1 && temp > max))return 1;
			//如果以上条件都执行完了,返回并结束ans
			return ans;
		}
		
		//如果以上全部语句都执行完了,那么表示此时的ans就是行动方案的全部种数
		return ans%MOD;
	}

}

总结:思路总是很难想到的,就是不知道题目做多了,思路会不会有呢?

十、矩阵翻硬币

小明先把硬币摆成了一个 n 行 m 列的矩阵。

随后,小明对每一个硬币分别进行一次 Q 操作。

对第x行第y列的硬币进行 Q 操作的定义:将所有第 ix 行,第 jy 列的硬币进行翻转。

其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。

当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。

小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。

聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。

【数据格式】
输入数据包含一行,两个正整数 n m,含义见题目描述。
输出一个正整数,表示最开始有多少枚硬币是反面朝上的。

【样例输入】
2 3

【样例输出】
1

【数据规模】
对于10%的数据,n、m <= 10^3;
对于20%的数据,n、m <= 10^7;
对于40%的数据,n、m <= 10^15;
对于10%的数据,n、m <= 10^1000(10的1000次方)。

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值