蓝桥杯2014年JavaB组

武功秘籍

将信息输出一下,手动判断就可以。答案为7

package Contest_2014;
/**
 * 答案是7
 * @author Admin
 *
 */
public class 武功秘籍 {

	public static void main(String[] args) {
		int num = 0;
		for (int i = 10; i <= 92; i += 2) {
			num++;
			System.out.printf("第%d与第%d页在相对页码%d上。\n", i, i + 1, num);
		}
	}

}

切面条

找规律递推,答案为1025

package Contest_2014;

/**
 * 
 * 标题:切面条
 * 
 * 一根高筋拉面,中间切一刀,可以得到2根面条。
 * 
 * 如果先对折1次,中间切一刀,可以得到3根面条。
 * 
 * 如果连续对折2次,中间切一刀,可以得到5根面条。
 * 
 * 那么,连续对折10次,中间切一刀,会得到多少面条呢?
 * 
 * 答案是个整数,请通过浏览器提交答案。不要填写任何多余的内容。
 * 
 * 
 * @author Admin
 *
 */
public class 切面条 {
	// 0 1 2 3
	// 2 3 5 9
	public static void main(String[] args) {
		// 递推
		int a = 2;
		for (int i = 1; i <= 10; i++) {
			int num = 2 * a - 1;
			System.out.printf("对折%d次,切割后得到%d根面条。\n", i, num);
			a = num;
		}
	}

}

猜字母

用StringBuider模拟一下,答案为q

package Contest_2014;

/**
 * 
 * 标题:猜字母
 * 
 * 把abcd...s共19个字母组成的序列重复拼接106次,得到长度为2014的串。
 * 
 * 接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字母。
 * 
 * 得到的新串再进行删除奇数位置字母的动作。如此下去,最后只剩下一个字母,请写出该字母。
 * 
 * 答案是一个小写字母,请通过浏览器提交答案。不要填写任何多余的内容。
 *
 * 答案是q
 * 
 * @author Admin
 *
 */
public class 猜字母 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String temp = "abcdefghijklmnopqrs";
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 106; i++) {
			sb.append(temp);
		}
		// 把偶数位置的字母放进新的StringBuilder中
		while (sb.length() != 1) {
			StringBuilder newSb = new StringBuilder();
			char[] chs = sb.toString().toCharArray();
			for (int i = 0; i < chs.length; i++) {
				if ((i + 1) % 2 == 0)
					newSb.append(chs[i]);
			}
			// 迭代
			sb = newSb;
			System.out.println(sb.toString());
		}
	}

}

大衍数列

白给题

package Contest_2014;

/**
 * 
 * 标题:大衍数列
 * 
 * 中国古代文献中,曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。
 * 
 * 它的前几项是:0、2、4、8、12、18、24、32、40、50 ...
 * 
 * 其规律是:对偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。
 * 
 * 以下的代码打印出了大衍数列的前 100 项。
 * 
 * @author Admin
 *
 */
public class 大衍数列 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for (int i = 1; i < 100; i++) {
			if (i % 2 == 0) // 填空
				System.out.println(i * i / 2);
			else
				System.out.println((i * i - 1) / 2);
		}
	}

}

圆周率

答案为3.1415
观察一下x,知道它代表连分数。
然后将n取0,手动带进去算一下,发现这里最终的x是连分数+2。
但是公式的右侧是连分数+1,所以将x-1再根据公式得出PI。

package Contest_2014;

/**
 * 数学发展历史上,圆周率的计算曾有许多有趣甚至是传奇的故事。其中许多方法都涉及无穷级数。
 * 
 * 图1.png中所示,就是一种用连分数的形式表示的圆周率求法。
 * 
 * 下面的程序实现了该求解方法。实际上数列的收敛对x的初始值 并不敏感。
 * 
 * 结果打印出圆周率近似值(保留小数点后4位,并不一定与圆周率真值吻合)。
 * 
 * @author Admin
 *
 */
public class 圆周率 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		double x = 111;
		for (int n = 10000; n >= 0; n--) {
			int i = 2 * n + 1;
			x = 2 + (i * i / x);
		}
		// 此时x为连分数+2,故要先减去1再做除法
		System.out.println(String.format("%.4f", 4.0 / (x - 1)));

	}

}

奇怪的分式

答案为14
DFS套路,枚举所有的情况,再统计符合条件的情况。

package Contest_2014;

/**
 * 
 * 标题:奇怪的分式
 * 
 * 上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:
 * 
 * 1/4 乘以 8/5
 * 
 * 小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png)
 * 
 * 老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!
 * 
 * 对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢?
 * 
 * 请写出所有不同算式的个数(包括题中举例的)。
 * 
 * 显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。
 * 
 * 但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!
 * 
 * 注意:答案是个整数(考虑对称性,肯定是偶数)。请通过浏览器提交。不要书写多余的内容。
 * 
 * 答案为14
 * 
 * @author Admin
 *
 */
public class 奇怪的分式 {
	static int[] data;
	static int count;

	public static void main(String[] args) {
		data = new int[4];
		count = 0;
		dfs(0);
		System.out.println(count);
	}

	private static void dfs(int depth) {
		if (depth == 4) {
			check(data);
			return;
		}

		for (int i = 1; i <= 9; i++) {
			data[depth] = i;
			dfs(depth + 1);
		}
	}

	// a/b * c/d = ac/bd
	// 其中a!=b且c!=d
	private static void check(int[] data) {
		int a = data[0];
		int b = data[1];
		int c = data[2];
		int d = data[3];
		if (a == b && c == d)
			return;
		int ac = a * 10 + c;
		int bd = b * 10 + d;
		if (a * 1.0 / b * c * 1.0 / d == ac * 1.0 / bd) {
			System.out.printf("%d/%d * %d/%d = %d/%d\n", a, b, c, d, ac, bd);
			count++;
		}
	}
}

扑克序列

字典序全排列

package Contest_2014;

import java.util.Arrays;

/**
 * 
 * 标题:扑克序列
 * 
 * A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。
 * 要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。
 * 
 * 请填写出所有符合要求的排列中,字典序最小的那个。
 * 
 * 例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
 * 
 * 请通过浏览器提交答案。“A”一定不要用小写字母a,也不要用“1”代替。字符间一定不要留空格。
 * 
 * 答案为2342A3A4
 * 
 * @author Admin
 *
 */
public class 扑克序列 {
	static String[] data = { "A", "A", "2", "2", "3", "3", "4", "4" };
	static String[] comb;
	static int visit[];// 记录data[i]是否被抓取过

	public static void main(String[] args) {
		// init
		comb = new String[data.length];
		visit = new int[data.length];
		// 按字典序大小对数据进行排序
		Arrays.sort(data);
		// DFS全排列,再判断是否符合条件,输出符合条件的第一条数据后退出程序。
		dfs(0);
	}

	private static void dfs(int depth) {
		if (depth == comb.length) {
			if (check()) {
				// print
				for (int i = 0; i < comb.length; i++) {
					System.out.print(comb[i]);
				}
				System.out.println();
				System.exit(0);
			}
			return;
		}

		for (int i = 0; i < data.length; i++) {
			if (visit[i] == 0) {// data[i]未被使用过
				comb[depth] = data[i];
				visit[i] = 1;
				dfs(depth + 1);
				visit[i] = 0;// go back
			}
		}
	}

	private static boolean check() {
		int index = -1;
		int index2 = -1;
		int index3 = -1;
		int index4 = -1;
		for (int i = 0; i < comb.length; i++) {
			if (comb[i] == "4" && index == -1)
				index = i;
			else if (comb[i] == "4" && i - index != 5)
				return false;

			if (comb[i] == "A" && index2 == -1)
				index2 = i;
			else if (comb[i] == "A" && i - index2 != 2)
				return false;

			if (comb[i] == "2" && index3 == -1)
				index3 = i;
			else if (comb[i] == "2" && i - index3 != 3)
				return false;

			if (comb[i] == "3" && index4 == -1)
				index4 = i;
			else if (comb[i] == "3" && i - index4 != 4)
				return false;
		}
		return true;
	}

}

分糖果

白给题

package Contest_2014;

import java.util.Scanner;

/**
 * 
 * 标题:分糖果
 * 
 * 有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
 * 
 * 每个小朋友都把自己的糖果分一半给左手边的孩子。
 * 
 * 一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
 * 
 * 反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
 * 
 * 你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。
 * 
 * 【格式要求】
 * 
 * 程序首先读入一个整数N(2<N<100),表示小朋友的人数。 接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
 * 要求程序输出一个整数,表示老师需要补发的糖果数。
 * 
 * 例如:输入 3 2 2 4 程序应该输出: 4
 * 
 * 
 * @author Admin
 *
 */
public class 分糖果 {
	static int n;
	static int[] data;// 当前拥有的数目
	static int count;// 补糖的次数

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		init();
		for (int i = 0; i < n; i++) {
			data[i] = sc.nextInt();
		}
		while (!check()) {// 检查所有人的糖果数目是否相等
			// 分糖与补糖
			function1();
		}
		System.out.println(count);
	}

	private static void function1() {
		// update
		int temp = data[0];// 暂存第一个的数据,便于最后一个的计算
		for (int i = 0; i < data.length; i++) {
			if (i != n - 1)
				data[i] = data[i] + data[i + 1] / 2 - data[i] / 2;// data=curData+in-out
			else
				data[i] = data[i] + temp / 2 - data[i] / 2;// data=curData+in-out

			if (data[i] % 2 != 0) {// 补糖
				data[i]++;
				count++;
			}
		}
	}

	private static boolean check() {
		int key = data[0];
		for (int i = 1; i < data.length; i++) {
			if (data[i] != key)
				return false;
		}
		return true;
	}

	private static void init() {
		data = new int[n];
		count = 0;
	}

}

地宫取宝(42分暴力做法)

package Contest_2014;

import java.util.Scanner;

/**
 * 
 * 标题:地宫取宝
 * 
 * X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
 * 
 * 地宫的入口在左上角,出口在右下角。
 * 
 * 小明被带到地宫的入口,国王要求他只能向右或向下行走。
 * 
 * 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
 * 
 * 当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
 * 
 * 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
 * 
 * 【数据格式】
 * 
 * 输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
 * 
 * 接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
 * 
 * 要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。
 * 
 * 例如,输入: 2 2 2 1 2 2 1 程序应该输出: 2
 * 
 * 再例如,输入: 2 3 2 1 2 3 2 1 5 程序应该输出: 14
 * 
 * @author Admin
 *
 */
public class 地宫取宝 {
	static int[][] maze;
	static int[] record;// 记录沿途的宝物信息
	static int[] dx = { 1, 0 };
	static int[] dy = { 0, 1 };
	static int n;
	static int m;
	static int k;
	static int num;
	static int count;

	public static void main(String[] args) {
		init();
		record[num++] = maze[0][0];
		dfs(0, 0);
		System.out.println(count % 1000000007);
	}

	private static void dfs(int x, int y) {
		if (x == n - 1 && y == m - 1) {// 到达迷宫的出口处
			function(-1, 0, 0);
			return;
		}

		for (int i = 0; i < dx.length; i++) {
			int newX = x + dx[i];
			int newY = y + dy[i];
			if (newX < n && newY < m) {// 不越界
				record[num++] = maze[newX][newY];
				dfs(newX, newY);
				num--;// go back
			}
		}
	}

	private static void function(int max, int depth, int curNum) {
		if (curNum == k) {
			count++;
			return;
		}
		if (depth == num)// 越过record数组的有效长度
			return;

		// 毫无意义的剪枝。。。
		if (num - depth < k - curNum)
			return;

		// 不选
		function(max, depth + 1, curNum);
		// 选
		if (max < record[depth])
			function(record[depth], depth + 1, curNum + 1);
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		k = sc.nextInt();
		maze = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				maze[i][j] = sc.nextInt();
			}
		}
		record = new int[255];
		for (int i = 0; i < record.length; i++) {
			record[i] = -1;
		}
		count = 0;
		num = 0;
	}

}

地宫取宝(记忆化搜索AC)

待补充

package Contest_2014;

import java.util.Scanner;

public class 地宫取宝_记忆化搜索 {

	private static int n;
	private static int m;
	private static int k;
	private static int[][] maze;
	private static int dx[] = { 0, 1 };
	private static int dy[] = { 1, 0 };
	private static long[][][][] record;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		long count = 0;
		count += dfs(0, 0, 0, -1);// 注意初始maxVal要为-1,宝物的价值可能为0
		System.out.println(count);
	}

	// 返回在当前状态下,抵达终点时持有宝物数目为k件的行动方案数目
	private static long dfs(int x, int y, int num, int maxVal) {
		if (x == n - 1 && y == m - 1) {// 抵达终点
			if (num == k || (num == k - 1 && maze[x][y] > maxVal))
				return 1;
			return 0;
		}

		// 记忆化
		if (record[x][y][num][maxVal + 1] != -1) {// maxVal 初始化值为-1
			return record[x][y][num][maxVal + 1];
		}

		long temp = 0;// 在当前状态下,抵达终点时持有宝物数目为k件的行动方案数目
		for (int i = 0; i < dx.length; i++) {
			int newX = x + dx[i];
			int newY = y + dy[i];
			if (newX < n && newY < m) {
				// 对于当前点拾取
				if (maze[x][y] > maxVal)
					temp += dfs(newX, newY, num + 1, maze[x][y]);
				// 对于当前点不拾取
				temp += dfs(newX, newY, num, maxVal);
			}
		}
		// 保存记录
		temp %= 1000000007;
		record[x][y][num][maxVal + 1] = temp;
		return temp;
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		k = sc.nextInt();
		maze = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				maze[i][j] = sc.nextInt();
			}
		}
		record = new long[n][m][25][14];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				for (int k = 0; k < 25; k++) {
					for (int k2 = 0; k2 < 14; k2++) {
						record[i][j][k][k2] = -1;
					}
				}
			}
		}
	}

}

矩阵翻转硬币(暴力10分)

package Contest_2014;

import java.util.Scanner;

/**
 * 
 * 标题:矩阵翻硬币
 * 
 * 小明先把硬币摆成了一个 n 行 m 列的矩阵。
 * 
 * 随后,小明对每一个硬币分别进行一次 Q 操作。
 * 
 * 对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。
 * 
 * 其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。
 * 
 * 当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。
 * 
 * 小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。
 * 
 * 聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
 * 
 * 【数据格式】 输入数据包含一行,两个正整数 n m,含义见题目描述。 输出一个正整数,表示最开始有多少枚硬币是反面朝上的。
 * 
 * 【样例输入】 2 3
 * 
 * 【样例输出】 1
 * 
 * @author Admin
 *
 */
public class 矩阵翻硬币_暴力 {
	static int n;
	static int m;
	static int[][] martix;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		martix = new int[n + 1][m + 1];// 初始化为0,代表都是正面朝上
		for (int i = 1; i < martix.length; i++) {
			for (int j = 1; j < martix[i].length; j++) {
				function(i, j);// 执行Q操作
			}
		}
		int count = count();
		System.out.println(count);
	}

	private static int count() {
		int count = 0;
		for (int i = 1; i < martix.length; i++) {
			for (int j = 1; j < martix[i].length; j++) {
				if (martix[i][j] == 1)
					count++;
			}
		}
		return count;
	}

	// 对i*x行j*y列进行反转
	private static void function(int x, int y) {
		for (int i = 1; i * x < martix.length; i++) {
			for (int j = 1; j * y < martix[i].length; j++) {
				if (martix[i * x][j * y] == 0)
					martix[i * x][j * y] = 1;
				else
					martix[i * x][j * y] = 0;
			}
		}
	}

}

矩阵翻转硬币(AC)

参考1
参考2
找出数学规律
开平方的方法为牛顿逼近
考场上必然写不出来,直接暴力完事

package Contest_2014;

import java.math.BigInteger;
import java.util.Scanner;

/**
 * 假设在n行m列的矩阵中 [1,n]区间中有平方数{n1,n2,...}共a个 
 * [1,m]区间中有平方数{m1,m2,...}共b个
 * 则在矩阵中(ni,mi)位置的硬币,即被翻奇数次,等价于其原始状态为反面朝上
 * 这样的硬币在矩阵中,共有a*b个
 * 故本题实际上是计算sqrt(a)取整*sqrt(b)取整的值
 * 
 * 牛顿逼近法求大数平方根向下取整的结果
 * 
 * @author Admin
 *
 */
public class 矩阵翻硬币 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String n = sc.next();
		String m = sc.next();
		System.out.println(sqrt(n).multiply(sqrt(m)));// sqrt(n) * sqrt(m)
	}

	private static BigInteger sqrt(String num) {
		int len = num.length() / 2;
		if (num.length() % 2 != 0)
			len++;
		char[] ans = new char[len];
		for (int i = 0; i < ans.length; i++) {
			ans[i] = '0';
		}
		// 牛顿逼近
		BigInteger key = new BigInteger(num);
		for (int i = 0; i < len; i++) {// 枚举所有位置的数字
			for (int j = 0; j <= 9; j++) {
				ans[i] = (char) ('0' + j);
				BigInteger temp = new BigInteger(String.valueOf(ans));
				if (temp.pow(2).compareTo(key) == 1) {
					ans[i] -= 1;
					break;// 去枚举下一位数字
				}
			}
		}
		String str = String.valueOf(ans);// 将char数组转为字符串,准备构造BigInteger
		return new BigInteger(str);
	}
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值