希望决赛题目不搞我
先挂
#1 年龄问题
本题满分: 11分
问题描述
s夫人一向很神秘。这会儿有人问起她的年龄,她想了想说:
“20年前,我丈夫的年龄刚好是我的2倍,而现在他的年龄刚好是我的1.5倍”。
你能算出s夫人现在的年龄吗?
答案提交
注意,需要提交的是一个整数,不要填写任何多余的内容。
40
calcCode:
public class Test {
public static void main(String[] args) {
int n, age;
for (age = 999; age > 0; age--) {
double now = (int)(age * 1.5);
if ((n = (int)now) != now) continue;
if (n - age + 20 == age) break;
}
System.out.println(age);
}
}
简化了一下 check 用的算式,懂得都懂
#2 海盗与金币
本题满分: 29分
问题描述
12名海盗在一个小岛上发现了大量的金币,后统计一共有将近5万枚。
登上小岛是在夜里,天气又不好。由于各种原因,有的海盗偷拿了很多,有的拿了很少。
后来为了“均贫富”,头目提出一个很奇怪的方案:
每名海盗都把自己拿到的金币放在桌上。然后开始一个游戏。
金币最多的海盗要拿出自己的金币来补偿其他人。
补偿的额度为正好使被补偿人的金币数目翻番(即变为原来的2倍)。
游戏要一直进行下去,直到无法完成。
(当金币数最多的不只一个人或最多金币的人持有金币数不够补偿他人的)
游戏就这样紧张地进行了,一直进行了12轮,恰好每人都“放血”一次,
更离奇的是,刚好在第12轮后,每个人的金币数居然都相等了!! 这难道是天意吗?
请你计算,游戏开始前,所有海盗的初始金币数目,从小到大排列,中间有一个空格分开。
答案形如:
8 15 29 58 110 …
当然,这个不是正确答案。
答案提交
需要提交的是一行空格分开的整数,不要提交任何多余的内容。
分隔符要用一个西文的空格,不要用其它符号(比如逗号,中文符号等)
13 25 49 97 193 385 769 1537 3073 6145 12289 24577
calcCode:
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] coin = new int[12];
for (int sum = 45000; sum < 55000; sum+= 12) {
Arrays.fill(coin, sum / 12);
dfs(0, sum, coin);
}
}
static void dfs(int cur, int sum, int[] coin) {
if (cur == 12) {
for (int i = 0; i < 12; i++)
System.out.print(coin[i] + " ");
System.out.println();
} else {
int cnt = 0;
for (int i = 0; i < 12; i++) {
if (i == cur) continue;
if (1 == (coin[i] & 1)) return;
cnt += coin[i] /= 2;
}
coin[cur] = sum - cnt;
dfs(cur + 1, sum, coin);
}
}
}
#3 全排列
本题满分: 25分
问题描述
对于某个串,比如:“1234”,求它的所有全排列。
并且要求这些全排列一定要按照字母的升序排列。
对于“1234”,应该输出(一共4!=24行):
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
下面是实现程序,请仔细分析程序逻辑,并填写划线部分缺少的代码。
// 轮换前k个,再递归处理
import java.util.*;
public class A
{
static void permu(char[] data, int cur){
if(cur==data.length-1){
System.out.println(new String(data));
return;
}
for(int i=cur; i<data.length; i++){
char tmp = data[i];
for(int j=i-1; j>=cur; j--) data[j+1] = data[j];
data[cur] = tmp;
permu(data, cur+1);
tmp = data[cur];
__________________________________________ ;
data[i] = tmp;
}
}
static void permu(String x){
permu(x.toCharArray(),0);
}
public static void main(String[] args){
permu("1234");
}
}
答案提交
请注意:只需要填写划线部分缺少的内容,不要抄写已有的代码或符号。
for (int j =cur; j <i; j++) data[j] = data[j+1];
#4 约瑟夫环
时间限制: 1.0s 内存限制: 256.0MB 本题满分: 49 分
问题描述
n 个人的编号是 1~n,如果他们依编号按顺时针排成一个圆圈,从编号是1的人开始顺时针报数。
(报数是从1报起)当报到 k 的时候,这个人就退出游戏圈。下一个人重新从1开始报数。
求最后剩下的人的编号。这就是著名的约瑟夫环问题。
本题目就是已知 n,k 的情况下,求最后剩下的人的编号。
输入格式
题目的输入是一行,2个空格分开的整数n, k。
输出格式
要求输出一个整数,表示最后剩下的人的编号。
测试样例1
Input:
10 3
Output:
4
评测用例规模与约定
0 < n,k < 1000000
code:
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws IOException {
int n = nextInt(System.in), k = nextInt(System.in), f = 0;
// f(n, k) = (f(n - 1, k) + k) % n;
for (int i = 2; i <= n; i++)
f = (f + k) % i;
System.out.print(f + 1);
}
static int nextInt(InputStream in) throws IOException {
int n = 0, c = in.read();
while (c < '0' || c > '9') c = in.read();
while (c >='0' && c <='9') {
n = n * 10 + (c & 0xf);
c = in.read();
}
return n;
}
}
#5 交换次数
时间限制: 1.0s 内存限制: 256.0MB 本题满分: 81 分
问题描述
IT产业人才需求节节攀升。业内巨头百度、阿里巴巴、腾讯(简称BAT)在某海滩进行招聘活动。
招聘部门一字排开。由于是自由抢占席位,三大公司的席位随机交错在一起,形如:
ABABTATT,这使得应聘者十分别扭。
于是,管理部门要求招聘方进行必要的交换位置,使得每个集团的席位都挨在一起。即最后形如:
BBAAATTT 这样的形状,当然,也可能是:
AAABBTTT 等。
现在,假设每次只能交换2个席位,并且知道现在的席位分布,
你的任务是计算:要使每个集团的招聘席位都挨在一起需要至少进行多少次交换动作。
输入格式
输入是一行n个字符(只含有字母B、A或T),表示现在的席位分布。
输出格式
输出是一个整数,表示至少交换次数。
测试样例1
Input:
TABTABBTTTT
Output:
3
测试样例2
Input:
TTAAABB
Output:
0
评测用例规模与约定
输入字符串的长度n 不大于100000
code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = in.readLine();
int high = line.length(), res = high;
int[][] bat = new int[3][high + 1];
for (int i = 1; i <= high; i++) {
for (int k = 0; k < 3; k++)
bat[k][i] = bat[k][i - 1];
switch (line.charAt(i - 1)) {
case 'B': bat[0][i]++; break;
case 'A': bat[1][i]++; break;
case 'T': bat[2][i]++; break;
}
}
int[] queue = { 0, 1, 2, 0, 2, 1, 0 };
for (int k = 0; k < 6; k++) {
int[] left = bat[queue[k]], mid = bat[queue[k + 1]];
int leftlen = left[high],
midlen = mid[high],
len = leftlen + midlen;
int now = leftlen - left[leftlen] +
midlen - mid[len] + mid[leftlen] -
min(mid[leftlen], left[len] - left[leftlen]);
res = min(res, now);
}
System.out.println(res);
}
static int min(int a, int b) { return a < b ? a : b; }
}
枚举结果做比较,用前缀和优化时间复杂程度
#6 自描述序列
时间限制: 1.0s 内存限制: 256.0MB 本题满分: 105 分
问题描述
小明在研究一个序列,叫Golomb自描述序列,不妨将其记作{G(n)}。这个序列有2个很有趣的性质:
- 对于任意正整数n,n在整个序列中恰好出现G(n)次。
- 这个序列是不下降的。
以下是{G(n)}的前几项:
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
G{n} | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 4 | 5 | 5 | 5 | 6 | 6 |
给定一个整数n,你能帮小明算出G(n)的值吗?
输入格式
一个整数n。
输出格式
一个整数G(n)
测试样例1
Input:
13
Output:
6
评测用例规模与约定
对于30%的数据,1 <= n <= 1000000
对于70%的数据,1 <= n <= 1000000000
对于100%的数据,1 <= n <= 2000000000000000
20E14,很大的一个数字,暴力解是行不通的,只能靠找规律之内的了
G{n} | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ... |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
n | 1 | 3 | 5 | 8 | 11 | 15 | 19 | 23 | 28 | 33 | 38 | 44 | 50 | ... |
code:
import java.util.ArrayList;
import java.util.Scanner;
import java.util.List;
public class Main {
public static void main(String[] args) { System.out.print(G(new Scanner(System.in).nextLong())); }
static long G(long n) {
List<Long> list = new ArrayList();
list.add(0L);
int Gn = 0;
for (int i = 0; list.get(Gn) < n; Gn++) {
if (list.get(i) < Gn + 1) i++;
list.add(i + list.get(Gn));
}
return Gn;
}
}
优雅,但内存超限