非官方标注答案,如有不妥,请指出。
2011 模拟 java 本科
注意:
本套模拟题主要模拟命题形式与考核范围。真实竞赛题的数量、难度可能与此套模拟题有差异。
说明:
本试卷包含两种题型:“代码填空”与“程序设计”。
填空题要求参赛选手在弄清给定代码工作原理的基础上填写缺失的部分,使得程序逻辑正确、完整。所填写的代码不多于一条语句(即不能出现分号)。
编程题要求选手设计的程序对于给定的输入能给出正确的输出结果。注意:在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。选手的程序必须是通用的,不能只对试卷中给定的数据有效。
1. 代码填空(满分2分)
在A B C D E F 六人中随机抽取3人中奖,要求中奖人不能重复。请完善以下代码:
public class MyTest
{
public static void main(String[] args)
{
Vector a = new Vector();
for(char i='A'; i<='F'; i++) a.add("" + i);
for(int k=0; k<3; k++)
{
int d = ____________________________;
(new Random()).nextInt(a.size());
System.out.println(a.remove(d));
}
}
}
2. 代码填空(满分3分)
不同进制的数值间的转换是软件开发中很可能会遇到的常规问题。下面的代码演示了如何把键盘输入的3进制数字转换为十进制。试完善之。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
int n = 0;
for(int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if(c<'0' || c > '2') throw new RuntimeException("Format error");
n = ______________________; 3*n+(c-'0')
}
System.out.println(n);
3. 代码填空(满分4分)
有如下程序,完成的功能为:找出数组中的最大元素。请填写程序的中空白,使程序运行正确。
public class test
{
public static void main(String[] args) {
int array[]={0,34,67,90,21,-9,98,1000,-78};
System.out.println(new test().findMax (array, 0));
}
public int findMax(int array[],int index)
{
if(array==null || array.length==0)
{
return 0;
}
int max=array[0];
if(index<array.length-1)
{
max=____________________ findMax(array,index+1);
}
if(max<array[index]) max= array[index];
return max;
}
}
4. 代码填空(满分5分)
电视台开宝箱节目:打进电话的人可以开启一个宝箱。箱子中有一件礼品。礼品是iphone的机率为1/12;是mp3 的机率为1/5;是洗衣粉的机率为1/2;剩余是KFC优惠券。
每次打进电话,宝箱会重置。
以下程序模拟了该抽奖过程。请填写缺失的部分。
public static void main(String[] args)
{
int i = (int) Math.random() * _____________; 60
if (i < 5) {
System.out.println("恭喜中了:iphone手机");
}else if (i < 17) {
System.out.println("恭喜中了:mp3");
} else if (i < 47) {
System.out.println("恭喜中了:洗衣粉");
} else {
System.out.println("恭喜中了:KFC优惠券");
}
}
5. 代码填空(满分6分)
下列代码求出一个二进制串中连续的1或连续的0出现的最大次数。请填缺失代码。
例如:s = “101100111100011”
则返回:4
又例如:s=”0111100000”
则返回:5
public static int getMaxContinuity(String s)
{
int max_1 = 0;
int max_0 = 0;
int n_1 = 0; // 当前1连续的次数
int n_0 = 0; // 当前0连续的次数
for(int i=0; i<s.length(); i++)
{
if(s.charAt(i)=='0')
{
n_0++;
________; n_1=0
}
else
{
n_1++;
_________; n_0 = 0
}
if(n_1 > max_1) max_1 = n_1;
if(n_0 > max_0) max_0 = n_0;
}
return max_1>max_0? max_1 : max_0);
}
6. 代码填空(满分9分)
下列代码把16进制表示的串转换为3进制表示的串。试完善之。
例如:x=“5”
则返回:“12”
又例如:x=”F”
则返回:“120”
private static int getRealValue(char x)
{
if(x>='0' && x<='9') return x-'0';
if(x>='a' && x<='f') return x-'a'+10;
if(x>='A' && x<='F') return x-'A'+10;
return 0;
}
public static String jin_zhi_16_3(String x)
{
int n = 0; // 累加真值
for(int i=0; i<x.length(); i++)
{
n = _________ + getRealValue(x.charAt(i)); // 填空 16*n
}
String t = "";
for(;;)
{
if(n==0) break;
t = (n % 3) + t;
_____________; // 填空 n=n/3
}
return t;
}
7. 代码设计(满分5分)
625这个数字很特别,625的平方等于390625,刚好其末3位是625本身。除了625,还有其它的3位数有这个特征吗?
请编写程序,寻找所有这样的3位数:它的平方的末3位是这个数字本身。
输出结果中,从小到大,每个找到的数字占一行。比如那个625就输出为:
625
public class MyTest {
public static void main(String[] args) {
for(int i=100;i<1000;i++){
if(i*i%1000 == i){
System.out.println(i);
}
}
}
}
8. 代码设计(满分11分)
考虑方程式:a^3 + b^3 = c^3 + d^3
其中:“^”表示乘方。a、b、c、d是互不相同的小于30的正整数。
这个方程有很多解。比如:
a = 1,b=12,c=9,d=10 就是一个解。因为:1的立方加12的立方等于1729,而9的立方加10的立方也等于1729。
当然,a=12,b=1,c=9,d=10 显然也是解。
如果不计abcd交换次序的情况,这算同一个解。
你的任务是:找到所有小于30的不同的正整数解。把a b c d按从小到大排列,用逗号分隔,每个解占用1行。比如,刚才的解输出为:
1,9,10,12
不同解间的顺序可以不考虑。
public class MyTest {
public static void main(String[] args) {
for(int a=1;a<=26;a++){
for(int b=a+1;b<=27;b++){
for(int c=b+1;c<=28;c++){
for(int d=c+1;d<=29;d++){
if(a*a*a+d*d*d==b*b*b+c*c*c){
System.out.println(a+","+b+","+c+","+d);
}
}
}
}
}
}
}
9. 代码设计(满分18分)
整数的分划问题。
如,对于正整数n=6,可以分划为:
6
5+1
4+2, 4+1+1
3+3, 3+2+1, 3+1+1+1
2+2+2, 2+2+1+1, 2+1+1+1+1
1+1+1+1+1+1+1
现在的问题是,对于给定的正整数n,编写算法打印所有划分。
用户从键盘输入 n (范围1~10)
程序输出该整数的所有划分。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int x = in.nextInt();
List expressions[] = new List[x];
for(int i=1;i<=x;i++){
if(i==1){
expressions[i-1] = new ArrayList();
expressions[i-1].add("1");
}else{
expressions[i-1] = new ArrayList();
expressions[i-1].add(String.valueOf(i));
//expressions[i-1].add(String.valueOf(i-1)+"+1");
for(int j=i-1;j>=i/2;j--){
for(int k=0;k<expressions[j-1].size();k++){
// 原来的表达式
String str1=(String)expressions[j-1].get(k);
// 排序后的表达式
String str2=process(str1+"+"+(i-j));
// 查找是否已经存在
boolean b=false;
for(int kk=0;kk<expressions[i-1].size();kk++){
if(expressions[i-1].get(kk).toString().equals(str2)){
b = true;
break;
}
}
if(!b){
expressions[i-1].add(str2);
}
}
}
}
}
Collections.sort(expressions[x-1]);
String temp=null;
for(int i=expressions[x-1].size()-1;i>=0;i--){
String value = expressions[x-1].get(i).toString();
if(temp==null){
System.out.print(value);
temp = value.substring(0,1);
}else{
if(value.startsWith(temp)){
System.out.print(",");
}else{
System.out.println();
temp = value.substring(0,1);
}
System.out.print(value);
}
}
}
/*
* 调整顺序,例如 3+1+2+1 调整后 3+2+1+1
*/
static String process(String exp){
exp = exp.replace("+"," ");
String str[] = exp.split(" ");
Arrays.sort(str);
StringBuffer sb = new StringBuffer();
for(int i=str.length-1;i>=0;i--){
sb.append(str[i]+"+");
}
sb.deleteCharAt(sb.length()-1);
return sb.toString();
}
}
10. 代码设计(满分20分)
一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。
例如:
当N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示5的3次方,也就是立方)。
当N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。
当N=5时,92727满足条件。
实际上,对N的每个取值,可能有多个数字满足条件。
程序的任务是:求N=21时,所有满足条件的花朵数。注意:这个整数有21位,它的各个位数字的21次方之和正好等于这个数本身。
如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求程序在3分钟内运行完毕。
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class ShuiXianHua {
// 449177399146038697307 9-4 8-1 7-4 6-2 5-0 4-3 3-3 2- 1-2 0-2
// 128468643043731391252 9-1 8-2 7-1 6-2 5-1 4-3 3-4 2-3 1-3 0-1
/*
* 思路:如果从000...000(21个)到99...99(21个)进行遍历,然后看21位数字的21次方之和是否等于这个数字本身,算法需要处理10的21次方,时间肯定不能满足要求
* 所以要减少遍历的次数,有些数字明显不合适:
* 考虑:21个1,他们的21次方的和才21,所以肯定不合适,不可能到21位数。
* 考虑:21个2,2的21次方大概是200万,再乘上21也才4000万,10的7次方,
* 哪个数字必须出现呢?可以算一下,使用下面的test方法测试。从结果可以看出如果21位数字中不包含8和9是没有办法组成21数字的,如果没有9则最少需要11个8,分这些情况考虑就可以了。
*/
public static void main(String[] args) {
//System.out.print(BigInteger.valueOf(10).pow(50).divide(BigInteger.valueOf(200)));
long l1 = System.nanoTime();
Date d1 = new Date();
// test();
List<State> allStates = new ArrayList<State>();
// 考虑9的情况
for(int i=1;i<=9;i++){
State newState = new State();
newState.sum = State.a21[9].multiply(BigInteger.valueOf(i));
newState.count = new int[11];
// Arrays.fill(newState.count,0);
newState.count[9] = i;
newState.count[10] = i;
newState.index = 8;
allStates.add(newState);
}
// 考虑8的情况
for(int i=10;i<=21;i++){
State newState = new State();
newState.sum = State.a21[8].multiply(BigInteger.valueOf(i));
newState.count = new int[11];
// Arrays.fill(newState.count,0);
newState.count[8] = i;
newState.count[10] = i;
newState.index = 7;
allStates.add(newState);
}
while(allStates.size()>0){
State tempState = allStates.get(allStates.size()-1);
// if(tempState.count[9]==4 && tempState.count[8]==1 &&tempState.count[7]==4
// && tempState.count[6]==2&& tempState.count[5]==0&& tempState.count[4]==3
// && tempState.count[3]==3){
// System.out.println("true");
// }
// System.out.println(allStates.size()+"-----"+tempState.index);
if(check(tempState)){
List<State> tt = tempState.nextState();
allStates.remove(allStates.size()-1);
allStates.addAll(tt);
}else{
allStates.remove(allStates.size()-1);
}
}
Date d2 = new Date();
long l2 = System.nanoTime();
System.out.println((d2.getTime()-d1.getTime()));
System.out.println((l2-l1)/1000);
}
// 需要继续处理返回true,否则返回false
public static boolean check(State state){
if(state.count[10]>21){
return false;
}
if(state.count[10] == 21){
String result = state.sum.toString();
if(result.length()!=21)
return false;
int tempCount[] = new int[10];
// Arrays.fill(tempCount,0);
for(int i=0;i<21;i++){
tempCount[result.charAt(i)-'0'] = tempCount[result.charAt(i)-'0']+1;
}
for(int i=0;i<10;i++){
if(tempCount[i]!=state.count[i]){ // 错误解
return false;
}
}
System.out.println(result);
return false;
}
return true;
}
public static void test(){
BigInteger max = BigInteger.valueOf(10).pow(21).subtract(BigInteger.valueOf(1));
BigInteger min = BigInteger.valueOf(10).pow(20);
for(int i=1;i<10;i++){
BigInteger temp = BigInteger.valueOf(i).pow(21);
int count1 = max.divide(temp).intValue();
int count2 = min.subtract(BigInteger.valueOf(1)).divide(temp).intValue()+1;
System.out.println(i+":最多需要"+count1+"个,最少需要"+count2+"个");
}
}
/*
* 运行结果:
*
1:最多需要-559939585个,最少需要1661992960个
2:最多需要1299066612个,最少需要988900121个
3:最多需要1109785847个,最少需要969972044个
4:最多需要227373675个,最少需要22737368个
5:最多需要2097151个,最少需要209716个
6:最多需要45585个,最少需要4559个
7:最多需要1790个,最少需要180个
8:最多需要108个,最少需要11个
9:最多需要9个,最少需要1个
*/
}
// 先考虑9,然后考虑8,然后...,state是中间的一个临时情况
class State{
// 最大值和最小值
static BigInteger max = BigInteger.valueOf(10).pow(21).subtract(BigInteger.valueOf(1));
// 记录0..9的21次方
static BigInteger a21[] = new BigInteger[10];
static{
for(int i=0;i<10;i++){
a21[i] = BigInteger.valueOf(i).pow(21);
}
}
// 记录各位数字的21次方的和
BigInteger sum ;
// 记录各位数字出现的次数,最后一个单元记录所有的数字的个数
int count[] = new int[11];
// 记录需要处理的数字,从9开始处理到0
int index;
// 根据当前情况,考虑下一层可能的情况,例如9个9的情况下,8有哪些可能
List<State> nextState(){
List<State> states = new ArrayList<State>();
if(index==0){
State newState = new State();
newState.sum = sum.add(BigInteger.valueOf(0));
newState.count = Arrays.copyOf(count,11);
newState.count[index] = 21-newState.count[10];
newState.count[10] = 21;
newState.index = -1;
states.add(newState);
return states;
}
int maxCount = max.subtract(sum).divide(a21[index]).intValue();
if(maxCount>21-count[10] || maxCount<0){
maxCount = 21-count[10];
}
// int maxCount = 21-count[10];
// 创建可能的情况
for(int i=0;i<maxCount;i++){
// if(a21[index].multiply(BigInteger.valueOf(i)).add(sum).compareTo(max)==1)
// continue;
State newState = new State();
newState.sum = sum.add(a21[index].multiply(BigInteger.valueOf(i)));
newState.count = Arrays.copyOf(count,11);
newState.count[index] = newState.count[index]+i;
newState.count[10] = newState.count[10]+i;
newState.index = index-1;
process(newState);
states.add(newState);
}
return states;
}
/*
* 为了提高效率,如果不处理,运行时间能够增加6、7倍。
*/
static void process(State state){
if(state.index<9){
BigInteger maxSum=state.sum.add(State.a21[state.index].multiply(BigInteger.valueOf(21-state.count[10])));
String result = state.sum.toString();
String maxResult = maxSum.toString();
int tempCount[] = new int[10];
// Arrays.fill(tempCount,0);
if(result.length()==maxResult.length()){
for(int i=0;i<result.length();i++){
char c1=result.charAt(i);
char c2=maxResult.charAt(i);
if(c1-c2==0){
tempCount[c1-'0']=tempCount[c1-'0']+1;
}else{
break;
}
}
for(int i=0;i<=state.index;i++){
int sub = tempCount[i]-state.count[i];
if(sub>0){
state.sum = state.sum.add(State.a21[i].multiply(BigInteger.valueOf(sub)));
state.count[i] = state.count[i]+sub;
state.count[10] = state.count[10]+sub;
}
}
}
}
}
}
我的笔记本(09年)上运行时间小于3秒,台式机(06年)不到7秒,使用递归,代码能够写的更少一些。