将信息输出一下,手动判断就可以。答案为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
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;
}
}
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;
}
}
待补充
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;
}
}
}
}
}
}
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;
}
}
}
}
参考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);
}
}