1.字符排序

算法是这样的,如果给定N个不同字符,将这N个字符全排列,最终的结果将会是N!种。如:给定 A、B、C三个不同的字符,则结果为:ABC、ACB、BAC、BCA、CAB、CBA一共3!=3*2=6种情况。

package Question1_9;
import java.util.Scanner;
import java.util.Vector;

public class Question1 {
	public static long count=0;
	private void fullPermutation(Vector<Character>sourse, Vector<Character> result) {
		if(sourse.size()==0){
			for (int i = 0; i < result.size(); i++) {
				System.out.print(result.elementAt(i));
			}
			System.out.print("\n");
			count++;
			return;
		}
				for (int i = 0; i < sourse.size(); i++) {
			Vector<Character>tsourse=new Vector<Character>(sourse);
			Vector<Character>tresult=new Vector<Character>(result);
			tresult.add(sourse.elementAt(i));
			tsourse.remove(i);
			new Question1().fullPermutation(tsourse, tresult);
		}
	}
	
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		Vector<Character> sourse=new Vector<Character>();
		Vector<Character> result=new Vector<Character>();
		for (int i = 0; i < n; i++) {
			sourse.add((char)('A'+i));
		}
		
		new Question1().fullPermutation(sourse, result);
		System.out.println(Question1.count);
	}
}

方法二:
import java.util.ArrayList;  
import java.util.Iterator;  
import java.util.LinkedHashSet;  
import java.util.List;  
import java.util.Scanner;  
import java.util.Set;  
  
public class Demo03 {  
    // 去掉重复元素,放入lis   
    public static void removeDuplicate(String s,Set<Character> lis){  
        for(char x:s.toCharArray()){  
            lis.add(x);  
        }  
    }  
    // 为方便操作 将 sets 转 lis    
    public static void convert(List<Character> lis,Set<Character> sets){  
        Iterator<Character> iter = sets.iterator();  
        while(iter.hasNext()){  
            lis.add(iter.next());  
        }  
    }  
    // 检测符合条件的元素组合   
    public static void check(Set<Character> sets){  
        List<Character> lis = new ArrayList<Character>();  
        convert(lis,sets);  // 为方便操作 将 sets 转 lis    
        StringBuffer sb = new StringBuffer();  
        for(int i=0;i<lis.size()-2;i++){  
            for(int j=i+1;j+1<lis.size();j++){   // 向后添加两位,所以 j+1<lis.size()   
                for(int k=j+1;k<lis.size();k++){  
                    sb.append(lis.get(i));  
                    sb.append(lis.get(j));  
                    sb.append(lis.get(k));  
                    System.out.println(sb); // 输出组合   
                    sb.setLength(0);    // 清空   
                }  
            }  
        }  
          
    }  
    public static void main(String[] args){  
        Scanner scan = new Scanner(System.in);  
        System.out.println("输入串(不大于30个字符)。");  
        String s = scan.nextLine();  
        Set<Character> sets = new LinkedHashSet<Character>();  
        removeDuplicate(s,sets);    // 去掉重复元素,放入lis   
        check(sets);    // 检测符合条件的元素组合   
    }  
}

运行结果:
输入串(不大于30个字符)。
abcd
abc
abd
acd
bcd

2.串的简单处理

串的处理
在实际的开发工作中,对字符串的处理是最常见的编程任务。
本题目即是要求程序对用户输入的串进行处理。具体规则如下:

  1. 把每个单词的首字母变为大写。
  2. 把数字与字母之间用下划线字符(_)分开,使得更清晰
  3. 把单词中间有多个空格的调整为1个空格。
    例如:
    用户输入:
    you and me what cpp2005program
    则程序输出:
    You And Me What Cpp_2005_program
    用户输入:
    this is a 99cat
    则程序输出:
    This Is A 99_cat
    我们假设:用户输入的串中只有小写字母,空格和数字,不含其它的字母或符号。
    每个单词间由1个或多个空格分隔。
    假设用户输入的串长度不超过200个字符。
package Question1_9;
import java.util.Scanner;
import java.util.Vector;

public class Question2 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		String string=scanner.nextLine();
		Vector<Character>vector=new Vector<Character>();
		for (int i = 0; i < string.length(); i++) {
			vector.add(string.charAt(i));
		}
		try {
			int index=0;
			while (index<vector.size()) {
				if(index==0&&vector.elementAt(index)>='a'&&vector.elementAt(index)<='z'){
					vector.set(index, (char)(vector.elementAt(index)-('a'-'A')));
				}else if(vector.elementAt(index-1)==' '&&vector.elementAt(index)==' '){
					vector.remove(index);
					index--;
				}else if (vector.elementAt(index-1)==' '&&(vector.elementAt(index)>='a'&&vector.elementAt(index)<='z')) {
					vector.set(index, (char)(vector.elementAt(index)-('a'-'A')));
				}else if((vector.elementAt(index)>='a'&&vector.elementAt(index)<='z')&&(vector.elementAt(index-1)>='0'&&vector.elementAt(index-1)<='9')){
					vector.add(index, '_');
					index++;
				}else if((vector.elementAt(index-1)>='a'&&vector.elementAt(index-1)<='z')&&(vector.elementAt(index)>='0'&&vector.elementAt(index)<='9')){
					vector.add(index, '_');
					index++;
				}
				index++;
			}
			for (int i = 0; i <vector.size(); i++) {
				System.out.print(vector.elementAt(i));
			}
			System.out.println();
		} catch (ArrayIndexOutOfBoundsException e) {
			// TODO: handle exception
		}
	}
}

运行结果:
you and me what cpp2005program
You And Me What Cpp_2005_program

3.猜算式

看下面的算式:
□□ x □□ = □□ x □□□
它表示:两个两位数相乘等于一个两位数乘以一个三位数。
如果没有限定条件,这样的例子很多。
但目前的限定是:这9个方块,表示1~9的9个数字,不包含0。
该算式中1至9的每个数字出现且只出现一次!
比如:
46 x 79 = 23 x 158
54 x 69 = 27 x 138
54 x 93 = 27 x 186

请编程,输出所有可能的情况!
注意:
左边的两个乘数交换算同一方案,不要重复输出!
不同方案的输出顺序不重要

package Question1_9;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Vector;

public class Question3 {
	public static long count=0;
	public static List<Vector<Character>> filteredNonRedundantResults;
	private static boolean isfilter(Vector<Character> result) {
		int a=(result.elementAt(0)-'0')*10+(result.elementAt(1)-'0');
		int b=(result.elementAt(2)-'0')*10+(result.elementAt(3)-'0');
		int c=(result.elementAt(4)-'0')*10+(result.elementAt(5)-'0');
		int d=(result.elementAt(6)-'0')*100+(result.elementAt(7)-'0')*10+(result.elementAt(8)-'0');
		if(a*b==c*d){
			return true;
		}
		return false;
	}
	public static void print(Vector<Character>vector) {
		System.out.printf("%c%c x %c%c = %c%c x %c%c%c",vector.elementAt(0),vector.elementAt(1),vector.elementAt(2),vector.elementAt(3),vector.elementAt(4),vector.elementAt(5),vector.elementAt(6),vector.elementAt(7),vector.elementAt(8));
	}
	private static void fullPermutation(Vector<Character>sourse, Vector<Character> result) {
		if(sourse.size()==0&&isfilter(result)){
			boolean exit=false;
			for (int i = 0; i < filteredNonRedundantResults.size(); i++) {
				int ra=(result.elementAt(0)-'0')*10+(result.elementAt(1)-'0');
				int rb=(result.elementAt(2)-'0')*10+(result.elementAt(3)-'0');
				int fa=(filteredNonRedundantResults.get(i).elementAt(0)-'0')*10+(filteredNonRedundantResults.get(i).elementAt(1)-'0');
				int fb=(filteredNonRedundantResults.get(i).elementAt(2)-'0')*10+(filteredNonRedundantResults.get(i).elementAt(3)-'0');
				if(ra==fb&&rb==fa){
					exit=true;
					break;
				}
			}
			if(exit==false){
				filteredNonRedundantResults.add(new Vector<Character>(result));
			}
			return;
		}
		for (int i = 0; i < sourse.size(); i++) {
			result.add(sourse.elementAt(i));
			sourse.remove(i);
			fullPermutation(sourse, result);
			sourse.add(i, result.elementAt(result.size()-1));
			result.remove(result.size()-1);
		}
	}
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int n=9;
		Vector<Character> sourse=new Vector<Character>();
		Vector<Character> result=new Vector<Character>();
		for (int i = 1; i <= n; i++) {
			sourse.add((char)('0'+i));
		}
		Question3.filteredNonRedundantResults=new ArrayList<Vector<Character>>();
		Question3.fullPermutation(sourse, result);
		for (int i = 0; i < Question3.filteredNonRedundantResults.size(); i++) {
			Question3.print(Question3.filteredNonRedundantResults.get(i));
			System.out.println();
		}
	}
}

运行结果:
46 x 79 = 23 x 158
54 x 69 = 27 x 138
54 x 93 = 27 x 186
58 x 67 = 29 x 134
58 x 69 = 23 x 174
58 x 73 = 29 x 146
58 x 96 = 32 x 174
63 x 74 = 18 x 259
64 x 79 = 32 x 158
73 x 96 = 12 x 584
76 x 98 = 14 x 532

方法二:
import java.util.List;
import java.util.ArrayList;
public class Demo01 {
static List lis = new ArrayList(); // 结果1(有重复的结果)
static List lis2 = new ArrayList(); // 结果2(去重复后的结果)
// 初始化数组为1~9
public static void init(int[] n) {
for(int i=0;i<9;i++){
n[i] = i+1; // 初始化数组为1~9
}
}
// 是否重复
public static boolean isDup(String s1,String s2){
String a1 = s1.substring(0,2);
String a2 = s1.substring(2,4);
String b1 = s2.substring(0,2);
String b2 = s2.substring(2,4);
if(a1.equals(b2)&&a2.equals(b1)){
return true;
}else{
return false;
}
}
// 去除lis重复元素
public static void removeDuplicate(){
lis2.add(lis.get(0));
for(int i=1;i<lis.size();i++){
boolean flag = true; // 标记是否重复
for(int j=0;j<lis2.size();j++){
flag = isDup(lis.get(i),lis2.get(j)); // 判断是否重复
if(flag) break; // 如果元素重复,直接跳出这层循环,测试下个数据
}
if(!flag){
lis2.add(lis.get(i)); // 不重复,则添加
}
}
}
// 输出
public static void print(){
for(String s:lis2){
String a = s.substring(0,2);
String b = s.substring(2,4);
String c = s.substring(4,6);
String d = s.substring(6);
System.out.println(a+” x “+b+” = “+c+” x “+d);
}
}
// 检测结果,符合条件的输出
public static void check(int[] n){
StringBuffer sb = new StringBuffer();
for(int x:n){ // 数字数组转为字符串
sb.append(x);
}
int a = Integer.parseInt(sb.substring(0,2).toString());
int b = Integer.parseInt(sb.substring(2,4).toString());
int c = Integer.parseInt(sb.substring(4,6).toString());
int d = Integer.parseInt(sb.substring(6).toString());
if(ab==cd){
lis.add(sb.toString()); // 添加结果
}
}
// 全排列进行测试
public static void allSort(int[] n,int start,int end){
if(start>=end){
check(n); // 检测结果,符合条件的输出
return ;
}else{
for(int i=start;i<=end;i++){
int t = n[start]; // 交换元素
n[start] = n[i];
n[i] = t;
// 递归全排列
allSort(n,start+1,end);
t = n[start]; // 还原元素
n[start] = n[i];
n[i] = t;
}
}
}
public static void fun(){
int[] n = new int[9];
init(n); // 初始化数组为1~9
allSort(n,0,n.length-1); // 全排列测试
removeDuplicate(); // 去除重复元素
}
public static void main(String[] args){
fun(); //
print(); // 输出结果
}
}

运行结果:
46 x 79 = 23 x 158
54 x 69 = 27 x 138
54 x 93 = 27 x 186
58 x 67 = 29 x 134
58 x 69 = 23 x 174
58 x 73 = 29 x 146
58 x 96 = 32 x 174
63 x 74 = 18 x 259
64 x 79 = 32 x 158
73 x 96 = 12 x 584
76 x 98 = 14 x 532

4.Excel地址转换

Excel是最常用的办公软件。每个单元格都有唯一的地址表示。比如:第12行第4列表示为:“D12”,第5行第255列表示为“IU5”。
事实上,Excel提供了两种地址表示方法,还有一种表示法叫做RC格式地址。
第12行第4列表示为:“R12C4”,第5行第255列表示为“R5C255”。
你的任务是:编写程序,实现从RC地址格式到常规地址格式的转换。
【输入、输出格式要求】
用户先输入一个整数n(n<100),表示接下来有n行输入数据。
接着输入的n行数据是RC格式的Excel单元格地址表示法。
程序则输出n行数据,每行是转换后的常规地址表示法。
例如:用户输入:
2
R12C4
R5C255
则程序应该输出:
D12
IU5
package Question1_9;
import java.util.Scanner;
import java.util.Stack;
import java.util.Vector;
public class Question4 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
scanner.nextLine(); //必须加上的,不然会导致输入不准确!
while (n>0) {
String string=scanner.nextLine();
String strings[]=string.split(“C”);
strings[0]=strings[0].substring(1, strings[0].length());
int hangshu=Integer.parseInt(strings[0]),lieshu=Integer.parseInt(strings[1]);//获取行数和列数
/*
* 对列数进行变换
*/
Stackstack=new Stack();
while(lieshu>0){
if(lieshu%26==0){
stack.push(‘Z’);
lieshu=lieshu/26-1;
}else {
stack.push((char)(‘A’-1+lieshu%26));
lieshu=lieshu/26;
}
}
while (!stack.empty()) {
System.out.print(stack.pop());
}
System.out.println(hangshu);
n–;
}
}
}
运行结果:
输入一个整数n(n<100)
2
R12C4
R5C255
D12
IU5

方法二:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Demo03 {
// 计算出字母的个数
public static int checkCount(int n){
int count = 1;
while(true){
int t = (int)Math.pow(26, count);
if(n > t){
count++;
n -= t;
}else{
return count;
}
}
}
// 添加余数对应的字母
public static char f(int n){
if(n26){
return ‘Z’;
}else{
return (char)(‘A’-1+n%26);
}
}
// 计算结果
public static String fun(int Row,int Col){
StringBuffer sb = new StringBuffer();
int count = checkCount(Col); // 计算出字母的个数
while(count>0){
if(Col%26
0){ //如果能除尽
// 例(702):702/26时(2余0) 应该分配成(1,26)
// 个位 加26(‘Z’)时 就等于 十位上的2 去掉(1个26),(一个(个位的26)对应一个(十位的1))
// 修改n的值 2-1; n就等于1; 这时就分配成了(1,26);
sb.insert(0,‘Z’); // 添加’Z’
Col = Col/26 -1;
}else{
sb.insert(0,f(Col));// 添加余数r对应的字母
Col /= 26; // 修改 n 的值
}
count–;
}
sb.append(Row); // RC地址后添加(行号)
return sb.toString();
}
// 输入数据
public static void input(String[] s){
Scanner scan = new Scanner(System.in);
int i = 0;
while(i<s.length){ // 输入n个数据
s[i++] = scan.nextLine();
}
}
// 拆分并计算结果
public static void splitOper(String[] s){
Pattern p = Pattern.compile(“[0-9]+”); // 以数字做分隔
for(int i=0;i<s.length;i++){
Matcher m = p.matcher(s[i]); // 得到所有数字
m.find(); // 得到第一个数字
int Row = Integer.parseInt(m.group()); // 取出第一个数字
m.find(); // 得到第二个数字
int Col = Integer.parseInt(m.group()); // 取出第二个数字
System.out.println(fun(Row,Col)); // 计算结果并输出
}
}
// 主函数
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入一个整数n(n<100)”);
String[] s = new String[scan.nextInt()];
input(s); // 输入数据
splitOper(s); // 拆分并计算结果
}
}

运行结果:
输入一个整数n(n<100)
2
R12C4
R5C255
D12
IU5

5.手机尾号评分

30年的改革开放,给中国带来了翻天覆地的变化。2011全年中国手机产量约为11.72亿部。手机已经成为百姓的基本日用品!给手机选个好听又好记的号码可能是许多人的心愿。
但号源有限,只能辅以有偿选号的方法了。
这个程序的目的就是:根据给定的手机尾号(4位),按照一定的规则来打分。其规则如下:

  1. 如果出现连号,不管升序还是降序,都加5分。例如:5678,4321都满足加分标准。
  2. 前三个数字相同,或后三个数字相同,都加3分。例如:4888,6665,7777都满足加分的标准。
    注意:7777因为满足这条标准两次,所以这条规则给它加了6分。
  3. 符合AABB或者ABAB模式的加1分。例如:2255,3939,7777都符合这个模式,所以都被加分。
    注意:7777因为满足这条标准两次,所以这条标准给它加了2分。
  4. 含有:6,8,9中任何一个数字,每出现一次加1分。例如4326,6875,9918都符合加分标准。其中,6875被加2分;9918被加3分。
    尾号最终得分就是每条标准的加分总和!
    要求程序从标准输入接收数据,在标准输出上输出结果。
    输入格式为:第一行是一个整数n(<100),表示下边有多少输入行,接下来是n行4位一组的数据,就是等待计算加分的手机尾号。
    例如,输入:
    14
    3045
    ….
    ……
    6789
    8866
    则输出:
    0
    0
    ….

    8
    5
    */

package Question1_9;
import java.util.Scanner;
import java.util.Stack;
import java.util.Vector;
public class Question5 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
scanner.nextLine();
while ((n–)>0) {
String telphone=scanner.nextLine();
int sum=0;
/*
* 情况一
/
if(telphone.charAt(0)-telphone.charAt(1)1){
char ch=telphone.charAt(0);
int index=0;
while (index<4&&ch
telphone.charAt(index)) {
ch–;
index++;
}
if(index>=4){
sum+=5;
}
}
if (telphone.charAt(0)-telphone.charAt(1)-1) {
char ch=telphone.charAt(0);
int index=0;
while (index<4&&ch
telphone.charAt(index)) {
ch++;
index++;
}
if(index>=4){
sum+=5;
}
}
/

* 情况二
*/
if (telphone.charAt(0)==telphone.charAt(1)&&telphone.charAt(1)==telphone.charAt(2)) {
sum+=3;
}
if(telphone.charAt(1)==telphone.charAt(2)&&telphone.charAt(2)==telphone.charAt(3)){
sum+=3;
}

		/*
		 * 情况三
		 */
		if(telphone.charAt(0)==telphone.charAt(1)&&telphone.charAt(2)==telphone.charAt(3)){
			sum+=1;
		}
		if(telphone.charAt(0)==telphone.charAt(2)&&telphone.charAt(1)==telphone.charAt(3)){
			sum+=1;
		}
		/*
		 * 情况四
		 */
		for (int i = 0; i < 4; i++) {
			if(telphone.charAt(i)=='6'||telphone.charAt(i)=='8'||telphone.charAt(i)=='9'){
				sum+=1;
			}
		}
		System.out.println(sum);
	}
}

}
运行结果:
14
3045
0211
……
……
……
8
5

方法二:
import java.util.Scanner;
public class Demo07 {
// 输入数据
public static void input(String[] n){
Scanner scan = new Scanner(System.in);
int i = 0;
while(i<n.length){
n[i++] = scan.nextLine();
}
}
// 得到分数
public static int getGrade(String n){
int s = 0; // 总分
char[] x = n.toCharArray();
int a = x[0]-‘0’;
int b = x[1]-‘0’;
int c = x[2]-‘0’;
int d = x[3]-‘0’;

    if(a+1==b&&b+1==c&&c+1==d||a-1==b&&b-1==c&&c-1==d){  
        s += 5; // 1.出现连号 +5分   
    }  
      
    if(a==b&&b==c){   
        s += 3; // 2.三个数字相同 (前三)+3分   
    }  
    if(b==c&&c==d){   
        s += 3; // 2.三个数字相同 (后三)+3分   
    }  
      
    if(a==b&&c==d){   
        s += 1; // 3.AABB模式 +1分   
    }  
    if(a==c&&b==d){   
        s += 1; // 3.ABAB模式 +1分   
    }  
      
    if(a==6||a==8||a==9){     
        s += 1; // 4.a含有:6 或 8 或 9  +1分   
    }  
    if(b==6||b==8||b==9){     
        s += 1; // 4.b含有:6 或 8 或 9  +1分   
    }  
    if(c==6||c==8||c==9){     
        s += 1; // 4.c含有:6 或 8 或 9  +1分   
    }  
    if(d==6||d==8||d==9){     
        s += 1; // 4.d含有:6 或 8 或 9  +1分   
    }  
    return s;  
}  
//  取得每一行分数并输出   
public static void fun(String[] n){  
    for(String x:n){      
        System.out.println(getGrade(x));  
    }  
}  
public static void main(String[] args){  
    Scanner scan = new Scanner(System.in);  
    String[] n = new String[scan.nextInt()];  
    input(n);   // 输入数据   
    fun(n);   
}

}

运行结果:
14
3045
0211
2345
6543
7777
8888
7878
7788
6688
2424
2244
9918
6789
8866
0
0
5
6
8
12
3
3
5
1
1
3
8
5

6.括号问题

下面的代码用于判断一个串中的括号是否匹配所谓匹配是指不同类型的括号必须左右呼应,可以相互包含,但不能交叉
例如:
…(…[…]…)… 是允许的
…(…[…)…]… 是禁止的
对于 main 方法中的测试用例,应该输出:
false
true
false
false
请分析代码逻辑,并推测划线处的代码。
答案写在“解答.txt”文件中
注意:只写划线处应该填的内容,划线前后的内容不要抄写。
import java.util.*;
publicclassDemo06 {
publicstaticboolean isGoodBracket(String s) {
Stack a = new Stack();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == ‘(’)
a.push(‘)’);
if (c == ‘[’)
a.push(‘]’);
if (c == ‘{’)
a.push(‘}’);
if (c == ‘)’ || c == ‘]’ || c == ‘}’) {
if (a.size()==0)
returnfalse; // 填空
if (a.pop() != c)
returnfalse;
}
}
if (a.size()!=0)
returnfalse; // 填空
returntrue;
}
publicstaticvoid main(String[] args) {
System.out.println(isGoodBracket(“…(…[.)…].{.(…).}…”));
System.out.println(isGoodBracket(“…(…[…].(.).).{.(…).}…”));
System.out.println(isGoodBracket(“…[…].(.).){.(…).}…”));
System.out.println(isGoodBracket(“…(…[…].(.).){.(…)…”));
}
}
运行结果:
false
true
false
false

7.扑克牌排列

下面代码模拟了一套扑克牌(初始排序A~K,共13张)的操作过程。
操作过程是:
手里拿着这套扑克牌,从前面拿一张放在后面,再从前面拿一张放桌子上,再从前面拿一张放在后面,…
如此循环操作,直到剩下最后一张牌也放在桌子上。
下面代码的目的就是为了求出最后桌上的牌的顺序。
初始的排列如果是A,2,3…K,则最后桌上的顺序为:
[2, 4, 6, 8, 10, Q, A, 5, 9, K, 7, 3, J]
请分析代码逻辑,并推测划线处的代码。
答案写在“解答.txt”文件中
注意:只写划线处应该填的内容,划线前后的内容不要抄写。
package Question1_9;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
public class Question7 {
public static List moveCard(List src) {
if (src == null)
return null;
List dst = new Vector();
for (;???? {
if (src.size()==0)
break; // 填空
src.add(src.remove(0));
dst.add(src.remove(0)); // 填空
}
return dst;
}
public static void main(String[] args) {
List a = new Vector();
a.addAll(Arrays.asList(“A”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”,
“10”, “J”, “Q”, “K”));

	System.out.println(moveCard(a));
}

}
运行结果:
[2, 4, 6, 8, 10, Q, A, 5, 9, K, 7, 3, J]

方法二:
import java.util.ArrayList;
public class Squeezer {
public static void main(String args[]){
ArrayList list=new ArrayList();
list.add(“K”);
list.add(“Q”);
list.add(“J”);
list.add(“10”);
list.add(“9”);
list.add(“8”);
list.add(“7”);
list.add(“6”);
list.add(“5”);
list.add(“4”);
list.add(“3”);
list.add(“2”);
list.add(“A”);
ArrayList out=new ArrayList();
out.add(list.get(0));
list.remove(0);
while(list.size()>0){
out.add(list.get(0));
list.remove(0);
out.add(out.get(0));
out.remove(0);
}
int i=out.size()-1;
while(i>0){
System.out.print(out.get(i–)+“,”);
}
System.out.print(out.get(0));
}
}

方法三:
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
public class Demo05 {
public static List moveCard(List src) {
if (src == null)
return null;
List dst = new Vector();
for (;???? {
if (src.size()==0)
break; // 填空
src.add(src.remove(0));
dst.add(src.remove(0)); // 填空
}
return dst;
}
public static void main(String[] args) {
List a = new Vector();
a.addAll(Arrays.asList(“A”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”,
“10”, “J”, “Q”, “K”));
System.out.println(moveCard(a));
}
}

运行结果:
[2, 4, 6, 8, 10, Q, A, 5, 9, K, 7, 3, J]

8.第一个数字(数字的值返回)

以下的静态方法实现了:把串s中第一个出现的数字的值返回。
如果找不到数字,返回-1
例如:
s = “abc24us43” 则返回2
s = “82445adb5” 则返回8
s = “ab” 则返回-1
以下的静态方法实现了:把串s中第一个出现的数字的值返回。
请分析代码逻辑,并推测划线处的代码。
答案写在“解答.txt”文件中
注意:只写划线处应该填的内容,划线前后的内容不要抄写。
publicclassDemo04 {
publicstaticint getFirstNum(String s) {
if (s == null || s.length() == 0)
return -1;
char c = s.charAt(0);
if (c >= ‘0’&& c <= ‘9’)
return s.charAt(0)-‘0’; // 填空
returngetFirstNum(s.substring(1)); // 填空
}
publicstaticvoid main(String[] args) {
String s1 = “abc24us43”; //则返回2
String s2 = “82445adb5”; //则返回8
String s3 = “ab”; //则返回-1
System.out.println(getFirstNum(s1));
System.out.println(getFirstNum(s2));
System.out.println(getFirstNum(s3));
}
}
运行结果:
2
8
-1

9.放麦子

你一定听说过这个故事。国王对发明国际象棋的大臣很佩服,
问他要什么报酬,大臣说:请在第1个棋盘格放1粒麦子,
在第2个棋盘格放2粒麦子,在第3个棋盘格放4粒麦子,
在第4个棋盘格放8粒麦子,…后一格的数字是前一格的两倍,
直到放完所有棋盘格(国际象棋共有64格)。
国王以为他只是想要一袋麦子而已,哈哈大笑。
当时的条件下无法准确计算,但估算结果令人吃惊:即使全世界都铺满麦子也不够用!
请你借助计算机准确地计算,到底需要多少粒麦子。
答案写在“解答.txt”中,不要写在这里!
package Question1_9;
import java.math.BigInteger;
publicclass Question9 {
publicstaticvoid main(String[] args) {
BigInteger total=new BigInteger(“0”);
BigInteger base=new BigInteger(“2”);
for (int i = 0; i < 64; i++) {
total=total.add(base.pow(i));
//System.out.println(total);
}
System.out.println(total);
System.out.println(base.pow(64).add(new BigInteger(“-1”)));

}

}
运行结果:
18446744073709551614

方法二:
import java.math.BigInteger;
public class Demo03 {
public static void main(String[] args) {
BigInteger bi = new BigInteger(“0”);
for(int i=0;i<64;i++){
bi = bi.add(BigInteger.valueOf((long)(Math.pow(2, i))));
}
System.out.println(bi);
}
}

10.求21位数的水仙花数

package Question10_19;
import java.math.BigInteger;
import java.util.Scanner;
class Question10Think2OptimizeMustRemember {
public static int size;
public static int array[]={0,1,2,3,4,5,6,7,8,9};
public static BigInteger powArray[] = new BigInteger[10]; // 记录0~9的size次方
public static int usedTimes[]=new int[10];// 记录0~9的使用次数
public static BigInteger iPowSizeMultiplyj[][]; //记录0到9中任意数字i的N次方乘以i出现的次数j的结果(i^N*j)
public static BigInteger MAX; // size位的数字能表示的最大值
public static BigInteger MIN; // size位的数字能表示的最小值
public static void init() {// 用于初始化powArray[],MAX,MIN
for (int i = 0; i < 10; i++) {// 初始化powArray[]
powArray[i] = (new BigInteger(“” + i)).pow(size);
}
MIN = (new BigInteger(“10”)).pow(size – 1); // 初始化最小值
MAX = (new BigInteger(“10”).pow(size).add(new BigInteger(“-1”)));// 初始化最大值
iPowSizeMultiplyj=new BigInteger[10][size+1]; //初始化iPowSizeMultiplyj[][]
for (int i = 0; i < 10; i++) {
iPowSizeMultiplyj[i][0]=BigInteger.valueOf(0);
for (int j = 1; j < size+1; j++) {
iPowSizeMultiplyj[i][j]=iPowSizeMultiplyj[i][j-1].add(powArray[i]);
}
}
}
public static void exhaustion(int arrayIndex,int used,BigInteger current) {
if (current.compareTo(MAX)>1) {//超过最大值,递归结束
return;
}

	if(used==size){//size位全部分配完毕
		if(current.compareTo(MIN)<0){ //已获得的值小于最小值
			return;
		}else {
			String s=current+"";
			int avaliableValueUsed[]=new int[10];
			for (int i = 0; i < s.length(); i++) {
				avaliableValueUsed[s.charAt(i)-'0']++;
			}
			for (int i = 0; i < 10; i++) {
				if(usedTimes[i]!=avaliableValueUsed[i]){
					return;
				}
			}
			System.out.println(current);
			return;
		}
	}
	if(arrayIndex==0){
		usedTimes[0]=size-used;
		exhaustion(-1, size, current);
		usedTimes[0]=0;
		return;
	}
	if(current.add(iPowSizeMultiplyj[arrayIndex][size-used]).compareTo(MIN)<0){
		return;
	}
	if(arrayIndex>=0){
		for (int i = 0; i <= size-used; i++) {
			if(current.add(iPowSizeMultiplyj[arrayIndex][i]).compareTo(MAX)>0){
				return;
			}
			usedTimes[arrayIndex]=i;
			exhaustion(arrayIndex-1, used+i,current.add(iPowSizeMultiplyj[arrayIndex][i]));
			usedTimes[arrayIndex]=0;
		}
	}else {
		return;//1到9已分配完毕,不可再延伸了
	}
}
public static void main(String[] args) {

// Scanner scanner = new Scanner(System.in);
// Question10Think2.size = scanner.nextInt();
long startTime = System.currentTimeMillis(); // 程序开始时间
Question10Think2OptimizeMustRemember.size=21;
Question10Think2OptimizeMustRemember.init();

	Question10Think2OptimizeMustRemember.exhaustion(9, 0, BigInteger.valueOf(0));
	
	
	long endTime = System.currentTimeMillis();	// 程序结束时间
	System.out.println((endTime-startTime)/1000f+"秒");	// 运行总时
}

}
运行结果:
128468643043731391252
449177399146038697307
19.062秒

方法二:
/*

  • 求21位数的水仙花数
    */
    import java.math.BigInteger;

public class Demo01_BigInteger {
// 求 每个 i 的 21 次方
public static BigInteger p(int i){
BigInteger base = BigInteger.valueOf(i);
return base.pow(21);
}
public static void ji_suan(BigInteger[] pw,int[] nn){
BigInteger sum = BigInteger.ZERO;
for(int i=0;i<10;i++){
sum = sum.add(
pw[i].multiply(BigInteger.valueOf(nn[i])));
}
String s = “” + sum;
if(s.length()!=21) return;
// 确定各数字出现的多少次
int[] nn2 = new int[10];
for(int i=0;i<21;i++){
nn2[s.charAt(i)-‘0’]++;
}
for(int i=0;i<10;i++){
if(nn[i]!=nn2[i]) return;
}
System.out.println(s);
}
public static void f(BigInteger[] pw, int[] nn, int cur, int use){
if(cur==9){
nn[9] = 21 – use;
ji_suan(pw,nn);
return;
}
// 对当前位置所有可能进行枚举
for(int i=0;i<21-use;i++){
nn[cur] = i;
f(pw,nn,cur+1,use+i);
}
}
public static void main(String[] args){
long startTime = System.currentTimeMillis(); // 程序开始时间
BigInteger pw[] = new BigInteger[10];
for(int i=0;i<pw.length;i++){
pw[i] = p(i);
}
int nn[] = new int[10];
f(pw,nn,0,0);
System.out.println(“OK”);
long endTime = System.currentTimeMillis(); // 程序结束时间
System.out.println((endTime-startTime)/1000f+“秒”); // 运行总时间
}
}

运行结果:
128468643043731391252
449177399146038697307
OK
27.343秒

方法三:
import java.math.BigInteger;
import java.util.Arrays;
/**

  • 如题,求解21位花朵数的解法,要求在3分钟之内计算完成花朵数: N位整数,它等于各个位的数字的N次方之和, *
  • 例如有一个N位数字,a1a2a3a4…aN = a1^N +a2N+…aNN
  • @author hb
    */
    public class FlowerNum {
    private static int num = 21;
    private static BigInteger[] table = new BigInteger[10];
    private static int[] nums;
    private static int[] a=new int[10];

    public static void main(String[] args) {
    long time = System.currentTimeMillis();
    for (int i = 0; i < 10; i++)
    table[i] = BigInteger.valueOf(i).pow(num);
    nums = new int[num];
    find(nums, 0, 0);
    //f();
    time = System.currentTimeMillis() – time;
    System.out.println(time / 1000.0 + “s”);
    }
    /**

    • level表示第几位数,num表示第几位数的数字;
      /
      public static void find(int[] nums, int level, int num) {
      nums[level] = num;
      if (level == nums.length – 1) {
      BigInteger big = sum(nums);//当level为20时,表示nums数组下标为20即21位数字满后求和;
      int[] temp = getArray(big);//将得到的21位数和转化为整形数组;并返回;
      if (check(nums, temp))//测试是否是21位,并将数组复制给nums数组;
      System.out.println(big);//输出big数;
      return;
      }
      for (int i =num; i < 10; i++)//递归;查找21位数字符合条件的数;
      find(nums, level + 1, i);
      }
      /
      *
    • 检测长度,若符合条件就复制a2到a1;
    • @param a1
    • @param a2
    • @return
      /
      public static boolean check(int[] a1, int[] a2) {
      if (a1.length != a2.length)
      return false;
      //Arrays.sort(Arrays.copyOf(a1, a1.length));
      Arrays.sort(a1);
      Arrays.sort(a2);
      return Arrays.equals(a1, a2);
      }
      /
      *
    • 得到nums数组的数做为table下标的数的和。并返回;
    • @param nums
    • @return
      /
      public static BigInteger sum(int[] nums) {
      BigInteger sum = BigInteger.ZERO;
      for (int i = 0; i < nums.length; i++)
      sum = sum.add(table[nums[i]]);
      return sum;
      }
      /
      *
    • 将BigInteger转化为int[]类型数据;
    • @param big
    • @return
      */
      public static int[] getArray(BigInteger big) {
      String s = String.valueOf(big);
      char[] ch = s.toCharArray();
      int[] res = new int[ch.length];
      for (int i = 0; i < ch.length; i++)
      res[i] = ch[i] – ‘0’;
      return res;
      }

    public static void f(){
    for(a[0]=0;a[0]<=21;a[0]++){
    for(a[1]=0;a[1]<=21-a[0];a[1]++){
    for(a[2]=0;a[2]<=21-a[0]-a[1];a[2]++){
    for(a[3]=0;a[3]<=21-a[0]-a[1]-a[2];a[3]++){
    for(a[4]=0;a[4]<=21-a[0]-a[1]-a[2]-a[3];a[4]++){
    for(a[5]=0;a[5]<=21-a[0]-a[1]-a[2]-a[3]-a[4];a[5]++){
    for(a[6]=0;a[6]<=21-a[0]-a[1]-a[2]-a[3]-a[4]-a[5];a[6]++){
    for(a[7]=0;a[7]<=21-a[0]-a[1]-a[2]-a[3]-a[4]-a[5]-a[6];a[7]++){
    for(a[8]=0;a[8]<=21-a[0]-a[1]-a[2]-a[3]-a[4]-a[5]-a[6]-a[7];a[8]++){
    a[9]=21-a[0]-a[1]-a[2]-a[3]-a[4]-a[5]-a[6]-a[7]-a[8];
    BigInteger sum=BigInteger.ZERO;
    for(int i=0;i<10;i++){
    sum=sum.add(table[i].multiply(new BigInteger(String.valueOf(a[i]))));
    }
    if(String .valueOf(sum).length()21){
    String str=sum.toString();
    int b[]=new int[10];
    for(int index=0;index<str.length();index++){
    int flag=str.charAt(index)-‘0’;
    b[flag]+=1;
    }
    boolean f=true;
    int i=0;
    for(;????{
    if(i
    10)break;
    if(b[i]!=a[i]){f=false;break;}
    i++;
    }
    if(f)System.out.println(sum.toString());
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }

11.猜生日

今年的植树节(2012年3月12日),小明和他的叔叔还有小伙伴们一起去植树。
休息的时候,小明的同学问他叔叔多大年纪,他叔叔说:“我说个题目,看你们谁先猜出来!”
“把我出生的年月日连起来拼成一个8位数(月、日不足两位前补0)正好可以被今天的年、月、日整除!”
他想了想,又补充到:“再给个提示,我是6月出生的。”
根据这些信息,请你帮小明算一下,他叔叔的出生年月日。
答案写在“解答.txt”中,不要写在这里!
格式是年月日连成的8位数。
例如,如果是1948年6月12日,就写:19480612
package Question10_19;
publicclass Question11 {
publicstaticvoid main(String[] args) {
for (int i = 20120312; ; i–) {
String s=“”+i;
intyear=Integer.parseInt(s.substring(0, 4));
int month=Integer.parseInt(s.substring(4, 6));
int day=Integer.parseInt(s.substring(6, 8));

//		System.out.println(year+" "+month+" "+day);
		if(day==0||day>31){
			continue;
		}
		if(!(i%2012==0&&i%3==0&&i%12==0)){
			continue;
		}
		if(month!=6){
			continue;
		}
		System.out.println(i);
		break;
	}
}

}
运行结果:
19550604

方法二:
public class Demo02 {
public static void main(String[] args){
int n = 20120312;
String s = “”;
for(int i=19000601;i<=20130312;i++){
s = “”+i;
int d = Integer.parseInt(s.substring(6)); // 得到天
int m = Integer.parseInt(s.substring(4,6)); // 得到月
if(d0) continue;
if(d>=1&&d<31&&m
6&&i%20120&&i%30&&i%12==0){
System.out.println(i);
}
}
}
}

运行结果:
19550604

12.填算式

看这个算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每个五角星代表 1 ~ 9 的不同的数字。
这个算式有多少种可能的正确填写方法?
173 + 286 = 459
295 + 173 = 468
173 + 295 = 468
183 + 492 = 675
以上都是正确的填写法!
注意:
111 + 222 = 333 是错误的填写法!
因为每个数字必须是不同的!
也就是说:1~9中的所有数字,每个必须出现且仅出现一次!
注意:
不包括数字“0”!
注意:
满足加法交换率的式子算两种不同的答案。
所以答案肯定是个偶数!
注意:
只要求计算不同的填法的数目
不要求列出所有填写法
更不要求填写源代码

package Question10_19;
import java.util.Vector;
publicclass Question12 {
publicstaticintcount;
publicstaticvoid AllType(Vector sourse,Vectorresult) {
if(sourse.size()0){
//System.out.println(result);
int a=(result.elementAt(0)-‘0’)*100+(result.elementAt(1)-‘0’)*10+result.elementAt(2)-‘0’;
int b=(result.elementAt(3)-‘0’)*100+(result.elementAt(4)-‘0’)*10+result.elementAt(5)-‘0’;
int c=(result.elementAt(6)-‘0’)*100+(result.elementAt(7)-‘0’)*10+result.elementAt(8)-‘0’;
if(a+b
c){
System.out.printf(“%d + %d = %d\n”,a,b,c);
count++;
}
}else{
for (int i = 0; i < sourse.size(); i++) {
result.add(sourse.elementAt(i));
sourse.remove(i);
AllType(sourse, result);
sourse.add(i, result.elementAt(result.size()-1));
result.remove(result.size()-1);
}
}
}
publicstaticvoid main(String[] args) {
Vectorsourse=new Vector();
Vectorresult=new Vector();
for (int i = 1; i <= 9; i++) {
sourse.add((char)(‘0’+i));
}
AllType(sourse, result);
System.out.println(count);
}
}
运行结果:
124 + 659 = 783
125 + 739 = 864
127 + 359 = 486
…………
782 + 163 = 945
783 + 162 = 945
784 + 152 = 936
336

其他方法:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class T01 {
static List<int[]> lis = new ArrayList<int[]>();
// 输出所有组合
public static void print(){
for(int[] x:lis){
for(int y:x){
System.out.print(y);
}
System.out.println();
}
}
// 检测是否有重复元素
public static boolean check2(int[] n){
if(lis.size()0) return false;
for(int i=0;i<lis.size();i++){
int a = n[0]*100+n[1]*10+n[2];
int b = lis.get(i)[3]*100+lis.get(i)[4]*10+lis.get(i)[5];
if(a!=b){
return false;
}
}
return true;
}
// 检测,并添加符合的组合
public static void check(int[] n){
int a = n[0]*100+n[1]*10+n[2];
int b = n[3]*100+n[4]*10+n[5];
int c = n[6]*100+n[7]*10+n[8];
if(a+b
c){
if(!check2(n)){ // 如果不重复,则添加
lis.add(Arrays.copyOf(n, n.length));
}
}
}
// 全排列
public static void f(int[] n,int start,int end){
if(start>=end){
check(n); // 检测,并添加符合的组合
return ;
}else{
for(int i=start;i<n.length;i++){
int temp = n[start];
n[start] = n[i];
n[i] = temp;
f(n,start+1,end);
temp = n[start];
n[start] = n[i];
n[i] = temp;
}
}
}
public static void main(String[] args){
int[] n = {1,2,3,4,5,6,7,8,9};
f(n,0,n.length-1);
print(); // 输出结果
System.out.println(“总个数:”+lis.size()); // 输出个数
}
}
运行结果:
124659783
125739864
127359486
127368495
128439567
128367495





745218963
746235981
748215963
754182936
752184936
763182945
762183945
715248963
716238954
718245963
718236954
783162945
784152936
782154936
782163945
总个数:336

方法二:另一种方法,下列是0-9的组合,没排除0

public class Demo01 {
static int count=0;
public static void main(String[] args){
for(int i=1;i<=9;i++){ // 第一个数的百位
for(int j=0;j<=9;j++){ // 十位
for(int k=0;k<=9;k++){ // 个位
for(int l=1;l<=9;l++){ // 第二个数的百位
for(int m=0;m<=9;m++){ // 十位
for(int n=0;n<=9;n++){ // 个位
if(i!=j && i!=k && i!=l && i!=m && i!=n &&
j!=k && j!=l && j!=m && j!=n &&
k!=l && k!=m && k!=n &&
l!=m && l!=n &&
m!=n ){
int a = i100+j10+k;
int b = l100+m10+n;
int c = a + b;
int x,y,z;
if(c>99&&c<999){
x = c/100;
y = c%100/10;
z = c%10;
}else{
break;
}
if(x!=y&&x!=z&&y!=z &&
x!=i && x!=j && x!=k && x!=l && x!=m && x!=n &&
y!=i && y!=j && y!=k && y!=l && y!=m && y!=n &&
z!=i && z!=j && z!=k && z!=l && z!=m && z!=n ){
System.out.println(a+” + “+b+” = “+c);
count++;
}
}

                        }  
                    }  
                }  
            }  
        }  
    }  
    System.out.println("总个数:"+count);  
}

}

运行结果:
103 + 469 = 572
103 + 479 = 582
103 + 579 = 682
103 + 649 = 752
103 + 749 = 852
103 + 759 = 862
104 + 579 = 683
104 + 759 = 863
105 + 269 = 374

… + … = …
… + … = …
… + … = …
… + … = …
… + … = …

784 + 136 = 920
784 + 152 = 936
786 + 134 = 920
805 + 137 = 942
806 + 147 = 953
807 + 135 = 942
807 + 146 = 953
835 + 107 = 942
837 + 105 = 942
846 + 107 = 953
847 + 106 = 953
总个数:1088

13.纵横放火柴游戏

【编程题】(满分34分)
这是一个纵横火柴棒游戏。如图[1.jpg],在3×4的格子中,游戏的双方轮流放置火柴棒。其规则是:

  1. 不能放置在已经放置火柴棒的地方(即只能在空格中放置)。
  2. 火柴棒的方向只能是竖直或水平放置。
  3. 火柴棒不能与其它格子中的火柴“连通”。所谓连通是指两根火柴棒可以连成一条直线,
    且中间没有其它不同方向的火柴“阻拦”。
    例如:图[1.jpg]所示的局面下,可以在C2位置竖直放置(为了方便描述格子位置,图中左、下都添加了标记),
    但不能水平放置,因为会与A2连通。同样道理,B2,B3,D2此时两种方向都不可以放置。但如果C2竖直放置后,
    D2就可以水平放置了,因为不再会与A2连通(受到了C2的阻挡)。
  4. 游戏双方轮流放置火柴,不可以弃权,也不可以放多根。直到某一方无法继续放置,则该方为负(输的一方)。
    游戏开始时可能已经放置了多根火柴。
    你的任务是:编写程序,读入初始状态,计算出对自己最有利的放置方法并输出。
    如图[1.jpg]的局面表示为:
    00-1
    -000
    0100
    即用“0”表示空闲位置,用“1”表示竖直放置,用“-”表示水平放置。
    【输入、输出格式要求】
    用户先输入整数 n(n<100), 表示接下来将输入 n 种初始局面,每种局面占3行(多个局面间没有空白行)。
    程序则输出:每种初始局面情况下计算得出的最佳放置法(行号+列号+放置方式)。
    例如:用户输入:
    2
    0111
    -000
    -000
    1111

0010
则程序可以输出:
00-
211
不难猜出,输出结果的含义为:
对第一个局面,在第0行第0列水平放置
对第二个局面,在第2行第1列垂直放置
注意:
行号、列号都是从0开始计数的。
对每种局面可能有多个最佳放置方法(解不唯一),只输出一种即可。
例如,对第一个局面,001 也是正解;最第二个局面,201也是正解。

package Question10_19;
import java.util.Scanner;
publicclass Question13 {
publicstaticboolean isOk(char[][] state, int i, int j) {
if (state[i][j] == ‘-’) {
for (int j2 = j + 1; j2 < 4; j2++) {
if (state[i][j2] == ‘-’) {
returnfalse;
} elseif (state[i][j2] == ‘1’) {
returntrue;
}
}
for (int j2 = j – 1; j2 >= 0; j2–) {
if (state[i][j2] == ‘-’) {
returnfalse;
} elseif (state[i][j2] == ‘1’) {
returntrue;
}
}
} elseif (state[i][j] == ‘1’) {
for (int i2 = i + 1; i2 < 3; i2++) {
if (state[i2][j] == ‘1’) {
returnfalse;
} elseif (state[i2][j] == ‘-’) {
returntrue;
}
}
for (int i2 = i – 1; i2 >= 0; i2–) {
if (state[i2][j] == ‘1’) {
returnfalse;
} elseif (state[i2][j] == ‘-’) {
returntrue;
}
}
}
returntrue;
}
privatestaticvoid jasdklf(char[][] state) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if (state[i][j] == ‘0’) {
state[i][j] = ‘-’;
if (isOk(state, i, j)) {
System.out.println(i + “” + j + ‘-’);
return;
}
state[i][j] = ‘0’;
state[i][j] = ‘1’;
if (isOk(state, i, j)) {
System.out.println(i + “” + j + ‘1’);
return;
}
state[i][j] = ‘0’;
}
}
}
}
publicstaticvoid main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
char[][] state = newchar[3][4];
String s;
while ((n–) > 0) {
for (int i = 0; i < 3; i++) {
s = scanner.nextLine();
for (int j = 0; j < 4; j++) {
state[i][j] = s.charAt(j);
}
}
jasdklf(state);
}
}
}

方法二:
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
public class Demo05 {
static boolean flag = false; // 用来标记是否连通
static boolean flag2 = false; // 用来标记是否没有结果, 如果没有结果输出”空”;
// 初始化数组
public static void init(List<char[][]> lis,String[] s,int n){
for(int i=0;i<n;i++){
for(int j=i3;j<i3+3;j++){
lis.get(i)[j%3] = s[j].toCharArray();
}
}
}
// 创建n个数组 初始化,并存入lis
public static void input(List<char[][]> lis,int n){
Scanner scan = new Scanner(System.in);
for(int i=1;i<=n;i++){ // 创建数组
lis.add(new char[3][4]);
}
String[] s = new String[n3];
for(int i=0;i<n
3;i++){ // 行到输入的数据
s[i] = scan.nextLine();
}
init(lis,s,n); // 用输入的数据 初始化每个数组
}
// c=‘1’ 检查列上侧是否连通
public static boolean colU(char[][] m,int i,int j,char c){
if(i<0){
flag = true; // 都不连通
return flag;
}
if(m[i][j]‘0’){
return colU(m,i-1,j,c);
}else if(m[i][j]
‘1’){
flag = false; // 有一个 ‘1’ 则连通
return flag;
}else if(m[i][j]‘-’){
flag = true; // 有一个 ‘-’ 则不连通
return flag;
}
return flag;
}
// c=‘1’ 检查列下侧是否连通
public static boolean colD(char[][] m,int i,int j,char c){
if(i>=m.length){
flag = true; // 都不连通
return flag;
}
if(m[i][j]
‘0’){
return colD(m,i+1,j,c);
}else if(m[i][j]‘1’){
flag = false; // 有一个 ‘1’ 则连通
return flag;
}else if(m[i][j]
‘-’){
flag = true; // 有一个 ‘-’ 则不连通
return flag;
}
return flag;
}
// c=‘-’ 检查行左侧是否连通
public static boolean rowL(char[][] m,int i,int j,char c){
if(j<0){
flag = true; // 都不连通
return flag;
}
if(m[i][j]‘0’){
return rowL(m,i,j-1,c);
}else if(m[i][j]
‘1’){
flag = true; // 有一个 ‘1’ 则不连通
return flag;
}else if(m[i][j]‘-’){
flag = false; // 有一个 ‘-’ 则连通
return flag;
}
return flag;
}
// c=‘-’ 检查行右侧是否连通
public static boolean rowR(char[][] m,int i,int j,char c){
if(j>=m[i].length){
flag = true; // 都不连通
return flag;
}
if(m[i][j]
‘0’){
return rowR(m,i,j+1,c);
}else if(m[i][j]‘1’){
flag = true; // 有一个 ‘1’ 则不连通
return flag;
}else if(m[i][j]
‘-’){
flag = false; // 有一个 ‘-’ 则连通
return flag;
}
return flag;
}
// 当c=‘1’时 检查是否连通1111111111111111111
public static boolean check1(char[][] m, int i, int j, char c) {
if(colU(m,i,j,c)&&colD(m,i,j,c)){ // 是 ‘1’ 时 检查(上下)是否连通
flag = true;
}else{
return false;
}
return flag;
}
// 当c=’-‘时 检查是否连通——————-
public static boolean check2(char[][] m, int i, int j, char c) {
if(rowL(m,i,j,c)&&rowR(m,i,j,c)){ // 是 ‘-’ 时 检查(左右)是否连通
flag = true;
}else{
return false;
}
return flag;
}
// 检测并添加元素
public static void calc2(char[][] m,int i,int j){
if(check1(m, i, j, ‘1’)){ // 等于’1’时,行列都不连通
m[i][j] = ‘1’; // 则添加元素
}else if(check2(m, i, j, ‘-’)){// 等于’-‘时,行列都不连通
m[i][j] = ‘-’;// 则添加元素
}else{
flag2 = true; // 表示无结果
}
}
// 计算函数的入口
public static void calc(char[][] m){
for(int i=0;i<m.length;i++){
for(int j=0;j<m[i].length;j++){
if(m[i][j]==‘0’){
calc2(m,i,j); // 进入检测函数
}
if(flag){
String temp = i+“”+j+“”+m[i][j];
System.out.println(temp);
flag2 = false; // 如果有元素添加,那么就不为空!下边的就不必输出”空”值
break; // 如果添加过元素,则退出循环
}
}
if(flag){ // 如果添加过元素,则退出循环
flag = false;
break;
}
}
if(flag2){ // 如果无结果,则添加空
System.out.println(“空”);
flag2 = false; // 修改标记位
}
}
// 主函数
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
List<char[][]> lis = new ArrayList<char[][]>(); // 存放每个数组
System.out.print(“输入整数 n(n<100):”);
// 创建n个数组 初始化,并存入lis
input(lis,scan.nextInt());
// 计算函数的入口, 单独去每个数组去测试
for(int i=0;i<lis.size();i++){
calc(lis.get(i));
}
}
}

运行结果:
输入整数 n(n<100):2
0111
-000
-000
1111
————–
0010
001
201

14.古代赌局

【编程题】(满分23分)
俗话说:十赌九输。因为大多数赌局的背后都藏有阴谋。不过也不尽然,有些赌局背后藏有的是:“阳谋”。
有一种赌局是这样的:桌子上放六个匣子,编号是1至6。多位参与者(以下称玩家)可以把任意数量的钱押在某个编号的匣子上。
所有玩家都下注后,庄家同时掷出3个骰子(骰子上的数字都是1至6)。输赢规则如下:

  1. 若某一个骰子上的数字与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目赔付(即1比1的赔率)。
  2. 若有两个骰子上的数字与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目的2倍赔付(即1比2的赔率)。
  3. 若三个骰子上的数字都与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目的6倍赔付(即1比6的赔率)。
  4. 若玩家所押注匣子号与某个骰子示数乘积等于另外两个骰子示数的乘积,则玩家拿回自己的押注,庄家也不赔付(流局)。
  5. 若以上规则有同时满足者,玩家可以选择对自己最有利的规则。规则执行后,则庄家收获所有匣子上剩余的押注。
    乍一看起来,好像规则对玩家有利,庄家吃亏。但经过大量实战,会发现局面很难说,于是怀疑是否庄家做了手脚,
    庄家则十分爽快地说:可以由玩家提供骰子,甚至也可以由玩家来投掷骰子。
    你的任务是:通过编程模拟该过程。模拟50万次,假定只有1个玩家,他每次的押注都是1元钱,其押注的匣子号是随机的。
    再假定庄家有足够的资金用于赔付。最后计算出庄家的盈率(庄家盈利金额/押注总金额)。
    【输入、输出格式要求】
    程序无输入,程序运行输出庄家的盈率,四舍五入保留到小数后3位。
    【注意】
    请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
    请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。
    相关的工程文件不要拷入。
    请不要使用package语句。
    源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
    package Question10_19;
    importjava.util.Scanner;
    publicclass Question14 {
    publicstaticvoid main(String[] args) {
    int a,b,c,d,sum = 0;
    for (int i = 0; i < 500000; i++) {
    a=(int) (Math.random()6)+1;
    b=(int) (Math.random()6)+1;
    c=(int) (Math.random()6)+1;
    d=(int) (Math.random()6)+1;
    // System.out.println(a+” “+b+” “+c+” “+d);
    if(ab&&ac&&ad){
    sum-=6;
    }elseif((a
    b&&ac)||(ac&&ad)||(ab&&ad)){
    sum-=2;
    }elseif(a
    b||ac||ad){
    sum-=1;
    }elseif ((a
    b==c
    d)||(a
    c==b
    d)||(ad==bc)) {
    sum-=0;
    }else {
    sum+=1;
    }
    }
    System.out.printf(“%.3f”,sum/500000f);
    }
    }
    程序输出:
    0.021

方法二:
import java.math.BigDecimal;
public class Demo04 {
static int sum = 0; // 庄家总钱数
public static void f(int m,int n,int a,int b,int c){
if(na&&nb&&nc){
sum -= 6*m;
}else if(n
a&&nb||na&&nc||nb&&nc){
sum -= 2*m;
}else if(n
a||nb||nc){
sum -= m;
}else if(!(na==bc||nb==ac||nc==ab)){
sum += m;
}
}
public static void main(String[] args) throws Exception{
int m = 1; // 押注都是1元钱
int n; // 押注匣子号
int a; // 第一个骰子
int b; // 第二个骰子
int c; // 第三个骰子
for(int i=0;i<500000;i++){
n = (int)(Math.random()*6+1);
a = (int)(Math.random()*6+1);
b = (int)(Math.random()*6+1);
c = (int)(Math.random()*6+1);
f(m,n,a,b,c);
}
// float f = (new BigDecimal(sum).divide(new BigDecimal(500000),
// 3,BigDecimal.ROUND_HALF_UP)).floatValue();
// System.out.println(f);
double d = sum/500000f;
System.out.printf(“%.3f\n”,d);
}
}

运行结果:
0.025

结果2:
0.022

结果3:
0.024

15.源码变换

超文本标记语言(即HTML),是用于描述网页文档的一种标记语言。
HTML通过文本来描述文档显示出来应该具有的“样子”。它主要通过标签来定义对象的显示属性或行为。
如果把java的源文件直接拷贝到HTML文档中,用浏览器直接打开,会发现本来整齐有序的源文件变成了一团遭。
这是因为,文本中的许多回车和空格都被忽略了。而有些符号在html中有特殊的含义,引起了更复杂的局面。
为了源文件能正常显示,我们必须为文本加上适当的标签。对特殊的符号进行转义处理。
常用的有:
HTML 需要转义的实体:
& —>&
空格 —>
< —><

--->>

” —> ”
此外,根据源码的特点,可以把 TAB 转为4个空格来显示。
TAB —>
为了显示为换行,需要在行尾加
标签。
为了显示美观,对关键字加粗显示,即在关键字左右加标签。比如:
public
对单行注释文本用绿色显示,可以使用标签,形如:
//这是我的单行注释!
注意:如果“//”出现在字符串中,则注意区分,不要错误地变为绿色。
不考虑多行注释的问题 /* … / // /* … */

你的任务是:编写程序,把给定的源文件转化为相应的html表达。
【输入、输出格式要求】
与你的程序同一目录下,存有源文件 a.txt,其中存有标准的java源文件。要求编写程序把它转化为b.html。
例如:目前的 a.txt 文件与 b.html 文件就是对应的。可以用记事本打开b.html查看转换后的内容。用浏览器打开b.html则可以看到显示的效果。
注意:实际评测的时候使用的a.txt与示例是不同的。

package Question10_19;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
importjava.io.InputStreamReader;
import java.io.OutputStreamWriter;
publicclass Question15FinishedBefore {
private String BoldComments(String tempString, String note) {
returnnull;
}
publicstaticvoid main(String[] args) {
try {
File inFile = new File(“test.java”);
FileInputStream fileInputStream;
fileInputStream = new FileInputStream(inFile);
InputStreamReader inputStreamReader = newInputStreamReader(
fileInputStream);
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
File outFile = new File(“test.html”);
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
OutputStreamWriter outStreamWriter = new OutputStreamWriter(
fileOutputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outStreamWriter);
outStreamWriter.write(“\n”);
outStreamWriter.write(“\n”);
String tempString;
while ((tempString = bufferedReader.readLine()) != null) {
tempString = tempString.replaceAll(“&”, “&”);
tempString = tempString.replaceAll(” “, ” “);
tempString = tempString.replaceAll(”<”, “<”);
tempString = tempString.replaceAll(“>”, “>”);
int index1 = tempString.lastIndexOf(“//”);
int index2 = tempString.indexOf(“”“);
if (index1 != -1 && index2 == -1) {
String s1 = tempString.substring(0, index1);
String s2 = tempString.substring(index1);
s2 = “” + s2 + “”;
tempString = s1 + s2;
} elseif (index1 != -1 && index2 != -1) {
int startMark = -1, endMark = -1;
boolean isNote = true;
for (int i = 0; i < tempString.length(); i++) {
if (‘”’ == tempString.charAt(i)) {
if (startMark == -1) {
startMark = i;
} else {
endMark = i;
if (index1 > startMark && index1 < endMark) {
isNote = false;
break;
} else {
startMark = -1;
endMark = -1;
}
}
}
}
if (isNote == true) {
String s1 = tempString.substring(0, index1);
String s2 = tempString.substring(index1);
s2 = “” + s2 + “”;
tempString = s1 + s2;
}
}
tempString = tempString.replaceAll(“”“, “””);
tempString = tempString.replaceAll(“\t”,
”    “);
tempString = tempString.replaceAll(” public “,
” public “);
tempString = tempString.replaceAll(” class “,
” class “);
tempString = tempString.replaceAll(” static “,
” static “);
tempString = tempString.replaceAll(” void “,
” void “);
outStreamWriter.write(tempString + “
” + “\r\n”);
}
outStreamWriter.write(”\n\n”);
outStreamWriter.write(”\n”);
bufferedWriter.flush();
bufferedReader.close();
bufferedWriter.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
// 我的工具类
public class MyTool
{
public static void main(String[] args)
{
int a = 100;
int b = 20;
if(a>b && true)
System.out.println(a);
else
System.out.println(“this! //aaa//kkk”); // 测试注释显示是否正确
}
}

方法二:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;

public class Demo03 {
public static String process(String s){
StringBuffer sb = new StringBuffer();
char[] c = s.toCharArray();
for(int i=0;i<c.length;i++){
switch(c[i]){
case ‘&’: sb.append(“&”); break;
case ’ ‘: sb.append(” “); break;
case ‘<’: sb.append(”<“); break;
case ‘>’: sb.append(”>“); break;
case ‘”’: sb.append(“”“); break;
case ‘\t’: sb.append(” “); break;
default: sb.append(c[i]);
}
}
String t = sb.toString();
t = t.replaceAll(“public”, “public”);
t = t.replaceAll(“class”, “class”);
t = t.replaceAll(“static”, “static”);
t = t.replaceAll(“void”, “void”);
int n = t.lastIndexOf(”//“); // 找到最后边的 “//” 位置
if(n!=-1){
String temp = t.substring(n); //为注释 加绿色
t = t.replaceAll(temp, “”+temp+”“);
}
t = t+”
\n”;
return t;
}
public static void main(String[] args) throws Exception{
// 定义读取内容
BufferedReader br = new BufferedReader(new FileReader(“a.txt”));
// 定义输出内容
PrintWriter pw = new PrintWriter(“b.html”);
String s;
pw.write(“\n”);
while((s=br.readLine())!=null){
pw.write(process(s)); // 输出内容
}
pw.write(“”);
br.close();
pw.close();
System.out.println(“转换成功”);
}
}

a.txt
// 我的工具类
public class MyTool
{
public static void main(String[] args)
{
int a = 100;
int b = 20;
if(a>b && true)
System.out.println(a);
else
System.out.println(“this! //aaa//kkk”); // 测试注释显示是否正确
}
}

运行结果:
// 我的工具类
public class MyTool
{
public static void main(String[] args)
{
int a = 100;
int b = 20;
if(a>b && true)
System.out.println(a);
else
System.out.println(“this! //aaa//kkk”); // 测试注释显示是否正确
}
}

16.数量周期

复杂现象背后的推动力,可能是极其简单的原理。科学的目标之一就是发现纷
繁复杂的自然现象背后的简单法则。爱因斯坦的相对论是这方面的典范例证。
很早的时候,生物学家观察某区域某种昆虫的数量(称为虫口数)之逐年变化规律,
就十分迷惑:有的时候是逐渐增多达到一个平衡值。有的时候在两个数字间周期跳动。
有的时候则进入一片混乱,类似随机数字一样变化(称为混沌现象)。
慢慢地,人们从数学中更清晰地观察到了这一现象,并因此开创了:符号动力学、非线性动力学等研究领域。
一个著名的虫口数目简化模型如下:
x’ = x * (1 – x) * r
这里,x x’ r 都是浮点数。
其中,x 表示当年的虫口数,x’ 表示下一年的虫口数。
它们的取值范围在 0 与 1 之间,实际上表示的是:虫口的总数占环境所能支持的最大数量的比率。
r 是常数(环境参数),r的取值范围在 [0,4]。
令人惊讶的是:这个简单的迭代公式有着不同寻常的神秘性质!
一般来说,多次迭代后,虫口数的稳定模式与x的初始值无关,而与 r 有关!
例如:无论x初始值是多少,当 r = 2.5 的时候,x 多次迭代后会趋向于 0.6。
而当 r = 3.2 的时候,x 的值会趋向于在 0.799 与 0.513 之间周期性摆动。
那么,r = 3.62 的时候,你观察到有什么周期现象发生吗?

不需要提交源代码,只要写出你的结论即可!
答案写在:“解答.txt”中,不要写在这里。

publicclassDemo01 {
staticintcount = 100; // 执行100次退出
publicstaticvoid f(double x,double r){
if(count<=0) return;
x = x * (1 – x) * r;
System.out.println(x);
count–;
f(x,r);
}
publicstaticvoid main(String[] args){
double x = 0.2;
double r = 3.62;
f(x,r);
System.out.println(“网络某某结论:虫口数目函数呈锯齿状变化,” +
“虫口数目不存在连续两年增加和连续两年减少的情况。”);
}
}
运行结果:
0.5792000000000002
……
……
……
0.878401825611548
网络某某结论:虫口数目函数呈锯齿状变化,虫口数目不存在连续两年增加和连续两年减少的情况。

17.提取子串

串“abcba”以字母“c”为中心左右对称;串“abba”是另一种模式的左右对称。
这两种情况我们都称这个串是镜像串。特别地,只含有1个字母的串,可以看成是第一种模式的镜像串。
一个串可以含有许多镜像子串。我们的目标是求一个串的最大镜像子串(最长的镜像子串),
如果有多个最大镜像子串,对称中心靠左的优先选中。例如:“abcdeefghhgfeiieje444k444lmn”的最大镜像子串是:“efghhgfe”
下面的静态方法实现了该功能,请仔细阅读并分析代码,填写空白处的代码,使得程序的逻辑合理,结果正确。

方法一:
publicclassDemo02_two {
publicstatic String maxS(String s){
String maxS = “”;
char[] c = s.toCharArray();

	for(int i=0;i<c.length-1;i++){
		int mark = 0;	// 下标标记
		String temp = "";	// 记录一个镜像串
		if(c[i]==c[i+1]){
			for(;;){	// abba模式
				if((i-mark<0)||c[i-mark]!=c[i+mark+1]) break;
				mark++;
			}
			temp = s.substring(i-mark+1,i+mark+1);
		}elseif((i+2)<c.length&&c[i]==c[i+2]){
			for(;;){	// abcba模式
				if((i-mark<0)||c[i-mark]!=c[i+mark+2]) break;
				mark++;
			}
			temp = s.substring(i-mark+1,i+mark+2);
		}
		if(temp.length()>maxS.length()){
			maxS = temp;
		}
	}
	return maxS;
}
publicstaticvoid main(String[] args){
	String s = "abcdeefghhgfeiieje444k444lmn";
	System.out.println(maxS(s));
}

}
方法二:
publicclassDemo02 {
publicstatic String getMaxMirrorString(String s) {
String max_s = “”; // 所求的最大对称子串
for (int i = 0; i < s.length(); i++) {
// 第一种对称模式
int step = 1;
try {
for (;???? {
if (s.charAt(i – step) != s.charAt(i + step))
break;
step++;
}
} catch (Exception e) {
}
String s1 = s.substring(i – step + 1, i + step); // 填空1
// 第二种对称模式
step = 0;
try {
for (;???? {
if (s.charAt(i – step) != s.charAt(i + step + 1))
break; // 填空2
step++;
}
} catch (Exception e) {
}
String s2 = s.substring(i – step + 1, i + step + 1);
if (s1.length() > max_s.length())
max_s = s1;
if (s2.length() > max_s.length())
max_s = s2;
}
return max_s;
}
publicstaticvoid main(String[] args) {
String s = “abcdeefghhgfeiieje444k444lmn”;
System.out.println(getMaxMirrorString(s));
}
}
运行结果:
efghhgfe

18.取球博弈

今盒子里有n个小球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,
也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断。
我们约定:
每个人从盒子中取出的球的数目必须是:1,3,7或者8个。
轮到某一方取球时不能弃权!
A先取球,然后双方交替取球,直到取完。
被迫拿到最后一个球的一方为负方(输方)
请编程确定出在双方都不判断失误的情况下,对于特定的初始球数,A是否能赢?
程序运行时,从标准输入获得数据,其格式如下:
先是一个整数n(n<100),表示接下来有n个整数。然后是n个整数,每个占一行(整数<10000),表示初始球数。
程序则输出n行,表示A的输赢情况(输为0,赢为1)。
例如,用户输入:
4
1
2
10
18
则程序应该输出:
0
1
1
0
package Question10_19;
import java.util.Scanner;
publicclass Question18Think2MustRemember {
publicstaticbooleanarray[]=newboolean[10020];
publicstaticvoid main(String[] args) {
array[0]=true;
for (int i = 1; i <array.length; i++) {
array[i]=(i>=8&&!array[i-8])||(i>=7&&!array[i-7])||(i>=3&&!array[i-3])||(i>=1&&!array[i-1]);
}
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int total;
scanner.nextLine();
while ((n–)>0) {
total=scanner.nextInt();
System.out.println(array[total]?1:0);
}
}
}
运行结果:
4
1
2
10
18
输出结果:
0
1
1
0

方法二
public class Ball
{
// 按规则取,还剩下n个球时,先取的人能赢吗?
static boolean f(int n)
{
if(n==1) return false;
if(n>8)return !f(n-8)||!f(n-7)||!f(n-3)||!f(n-1);
if(n>7)return !f(n-7)||!f(n-3)||!f(n-1);
if(n>3)return !f(n-3)||!f(n-1);
else return !f(n-1);
}

public static void main(String[] args)
{
	System.out.println(f(10));
}

}

方法三:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Demo06 {
public static boolean contest(int n){
if(n>=1){
switch(n){
case 1 : return false; // 剩1个球,则输
case 3 : return false; // 剩3个球,则输
case 7 : return false; // 剩7个球,则输
case 8 : return true; // 剩8个球,则赢
// 如果不是不是1,3,7,8则 选择权交给B,B任然调用该函数,不过返回值需要取反
// 而此时A可以选的只有 1 3 7 8 所以用num减去之 逐个测试即可
default : return (!contest(n-8)||!contest(n-7)||
!contest(n-3)||!contest(n-1));
}
}else{
return false;
}
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
List lis = new ArrayList();
for(int i=0;i<n;i++){ // 输入数据
lis.add(scan.nextInt());
}
System.out.println(“输出结果:”);
for(int i=0;i<n;i++){
if(contest(lis.get(i))){
System.out.println(1);
}else{
System.out.println(0);
}
}
}
}

运行结果:
4
1
2
10
18
输出结果:
0
1
1
0

19.密码发生器

在对银行账户等重要权限设置密码的时候,我们常常遇到这样的烦恼:如果为了好记用生日吧,
容易被破解,不安全;如果设置不好记的密码,又担心自己也会忘记;如果写在纸上,担心纸张被别人发现或弄丢了…
这个程序的任务就是把一串拼音字母转换为6位数字(密码)。
我们可以使用任何好记的拼音串(比如名字,王喜明,就写:wangximing)作为输入,程序输出6位数字。
变换的过程如下:
第一步. 把字符串6个一组折叠起来,比如wangximing则变为:
wangxi
ming
第二步. 把所有垂直在同一个位置的字符的ascii码值相加,得出6个数字,如上面的例子,则得出:
228 202 220 206 120 105
第三步. 再把每个数字“缩位”处理:就是把每个位的数字相加,得出的数字如果不是一位数字,
就再缩位,直到变成一位数字为止。例如: 228 => 2+2+8=12 => 1+2=3
上面的数字缩位后变为:344836, 这就是程序最终的输出结果!
要求程序从标准输入接收数据,在标准输出上输出结果。
输入格式为:第一行是一个整数n(<100),表示下边有多少输入行,接下来是n行字符串,就是等待变换的字符串。
输出格式为:n行变换后的6位密码。
例如,输入:
5
zhangfeng
wangximing
jiujingfazi
woaibeijingtiananmen
haohaoxuexi
则输出:
772243
344836
297332
716652
875843

package Question10_19;
import java.util.Scanner;
publicclass Question19 {
publicstaticint simplify(int n) {
String s;
while (n>=10) {
s=n+“”;
n=0;
for (int i = 0; i < s.length(); i++) {
n+=s.charAt(i)-‘0’;
}
}
return n;
}
publicstaticvoid main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
String s;
scanner.nextLine();
while((n–)>0){
int array[]=newint[6];
s=scanner.nextLine();
for (int i = 0; i < s.length(); i++) {
array[i%6]+=(int)(s.charAt(i));
}
for (int i = 0; i < 6; i++) {
System.out.print(simplify(array[i]));
}
System.out.println();
}

// System.out.println(simplify(123456789));
}
}
运行结果:
输入整数n(<100)表示下边有多少输入行:
5
zhangfeng
wangximing
jiujingfazi
woaibeijingtiananmen
haohaoxuexi
772243
344836
297332
716652
875843

方法二:
import java.util.Scanner;
public class Demo04 {
// 缩位
public static char con(char[] c){
if(c.length<=1){
return c[0];
}
int temp = 0;
for(int i=0;i<c.length;i++){
temp += c[i]-‘0’;
}
c = (“”+temp).toCharArray();
return con©;
}
// 缩位处理,并输出结果
public static void condense(int[] n){
StringBuffer sb = new StringBuffer();
for(int i=0;i<n.length;i++){
char[] c = (“”+n[i]).toCharArray();
sb.append(con©); // 缩位
}
System.out.println(sb);
}
// 计算结果
public static void calc(char[][] c){
int[] n = new int[6];
int last = c[c.length-1].length ;
for(int i=0;i<6;i++){
for(int j=0;j<c.length-1;j++){
n[i] += c[j][i]; // 前几行列相加
}
}
for(int j=0;j<last;j++){
n[j] += c[c.length-1][j]; // 加上最后一行
}
condense(n); // 缩位处理,并输出结果
}
// 进入主要操作函数
public static void f(String s){
int t = (s.length()+5)/6; // 分为几组
char[][] c = new char[t][];
for(int i=0;i<t;i++){ // 得到分组后的数据
if(s.length()>6){
c[i] = s.substring(0, 6).toCharArray();
s = s.substring(6);
}else{
c[i] = s.substring(0, s.length()).toCharArray();
break;
}
}
calc©; // 计算结果
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in); // 输入整数
Scanner scan2 = new Scanner(System.in); // 输入字符串
System.out.println(“输入整数n(<100)表示下边有多少输入行:”);
int n = scan.nextInt();
String[] ss = new String[n];
int k=0;
while(k<n){
ss[k++] = scan2.nextLine();
}
for(int i=0;i<n;i++){
f(ss[i]);
}
}
}

运行结果:
输入整数n(<100)表示下边有多少输入行:
5
zhangfeng
wangximing
jiujingfazi
woaibeijingtiananmen
haohaoxuexi
772243
344836
297332
716652
875843

20.方阵顺时针旋转

对一个方阵转置,就是把原来的行号变列号,原来的列号变行号
例如,如下的方阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
转置后变为:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
但,如果是对该方阵顺时针旋转(不是转置),却是如下结果:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
下面的代码实现的功能就是要把一个方阵顺时针旋转。

publicclassDemo03 {
// 矩阵顺时针旋转
publicstaticvoid rotation(int[][] n,int [][] m,int i,int j){
int t = j; // 标记最后一行的位置
if(i>=n.length) return;
for(int k=0;k<n.length;k++){
m[i][k] = n[j–][i]; // 解决一行
}
rotation(n,m,++i,t); // 递归解决下一行
}
// 输出矩阵
publicstaticvoid print(int[][] t){
for(int[] x: t){
for(int y:x){
System.out.print(y+“\t”);
}
System.out.println();
}
}
publicstaticvoid main(String[] args){
int[][] n = {
{1 ,2 ,3 ,4 },
{5 ,6 ,7 ,8 },
{9 ,10,11,12},
{13,14,15,16}
};
print(n); // 显示原矩阵
int len = n.length;
int[][] m = newint[len][len]; // 目标矩阵
rotation(n,m,0,len-1); // 矩阵顺时针旋转
System.out.println(“顺时针旋转结果:”);
print(m); // 显示目标矩阵
}
}
运行结果:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
顺时针旋转结果:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4

21.古堡算式

福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式:
ABCDE * ? = EDCBA
他对华生说:“ABCDE应该代表不同的数字,问号也代表某个数字!”
华生:“我猜也是!”
于是,两人沉默了好久,还是没有算出合适的结果来。
请你利用计算机的优势,找到破解的答案。
把 ABCDE 所代表的数字写出来。
答案写在“解答.txt”中,不要写在这里!
publicclassTDemo02_two {
publicstaticvoid main(String[] args){
for(int i=10000;i<100000;i++){
int a = i/10000;
int b = i%10000/1000;
int c = i%10000%1000/100;
int d = i%10000%1000%100/10;
int e = i%10;
if(ab||ac||ad||ae||bc||bd||be||cd||ce||de){
continue;
}
int y = e10000+d1000+c100+b10+a;
if(y%i==0){
System.out.println(i+”“+y/i+”=”+y);
}
}
}
}
运行结果:
21978
4=87912

方法二:
public class Demo02 {
// 检查是否是全111111…
public static boolean check(int[] b){
boolean flag = true;
for(int i=0;i<b.length;i++){
if(b[i]0){
flag = false;
break;
}
}
return flag;
}
// 检查是否是一个五位数
public static boolean checkFive(int[] b){
boolean flag = false;
int count = 0;
for(int i=0;i<b.length;i++){
if(b[i]1){
count++;
}
}
if(count
5) flag = true;
return flag;
}
// 得到一个五位数字
public static String values(int[] b){
StringBuffer sb = new StringBuffer();
for(int i=0;i<b.length;i++){
if(b[i]!=0){
sb.append(i);
}
}
return sb.toString();
}
// 反转 n
public static int reverse(int n){
StringBuffer sb = new StringBuffer();
sb.append(n);
sb.reverse();
return Integer.parseInt(sb.toString());
}
// 进位得到下一个数字
public static void modify(int[] b){
b[b.length-1]++;
for(int i=b.length-1;i>0;i–){
if(b[i]>1){
b[i] = 0;
b[i-1]++;
}
}
}
public static void calc(String s){
int n = Integer.parseInt(s); // 得到一个五位数字
int r = reverse(n); // 反转 n
if(r%n
0) // 得到结果 n * ? = r
System.out.println(n+“*”+(r/n)+“=”+r);
}
public static void allSort(char[] c,int start,int end){
char temp = 0;
if(start==end){
String s = new String©;
if((s.charAt(0)-‘0’)!=0){
calc(s); // 计算结果
}
}else{
for(int i=start;i<=end;i++){
temp = c[start];
c[start] = c[i];
c[i] = temp;
allSort(c,start+1,end);
temp = c[start];
c[start] = c[i];
c[i] = temp;
}
}
}
public static void f(int[] b){
for(;????{
if(check(b)) break; // 检查是否是全111111…
modify(b); // 进位,进行下一个数字的测试
if(!checkFive(b)) continue; // 检查是否是一个五位数字
String s = values(b); // 得到一个五位数字
char[] c = s.toCharArray();
allSort(c,0,c.length-1); // 全排列其中一个五位数,并计算结果
}
}
public static void main(String[] args){
int[] b = new int[10];
f(b);
}
}

运行结果:
21978*4=87912

22.微生物增殖

假设有两种微生物 X 和 Y
X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍)。
一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1个Y。
现在已知有新出生的 X=10, Y=89,求60分钟后Y的数目。
如果X=10,Y=90 呢?
本题的要求就是写出这两种初始条件下,60分钟后Y的数目。
题目的结果令你震惊吗?这不是简单的数字游戏!真实的生物圈有着同样脆弱的性质!也许因为你消灭的那只 Y 就是最终导致 Y 种群灭绝的最后一根稻草!
请忍住悲伤,把答案写在“解答.txt”中,不要写在这里!
package Question20_29;
importjava.util.Scanner;
publicclass Question22MustRemember {
publicstaticvoid calculate(int primaryNumX,int primaryNumY,int timesOfMinute) {
int numX=primaryNumX,numY=primaryNumY;
for (int i = 2; i <=timesOfMinute2; i++) {
if(numY<=0){
numY=0;
break;
}
if(i%20){
numY-=primaryNumX;// 当为整数分钟时,最初数目的生物X将进食同等数目的生物Y
}
elseif(i%2
1){
numY-=(numX-primaryNumX); //当为半数分钟的奇数倍时,由最初的生物X增值产生的生物X将进食同等数目的生物Y
}
if(i%6==0){
numX
=2; //三分钟的整数倍,生物X增值一倍
}
if(i%4==0){
numY*=2; //两分钟的整数倍,生物Y增值一倍
}
}
System.out.println(numY);
}
publicstaticvoid main(String[] args) {

	calculate(10, 89, 60);
	calculate(10, 90, 60);

// Scanner scanner=new Scanner(System.in);
// int numX=scanner.nextInt(),numY=scanner.nextInt();
// System.out.println(numX+” “+numY);
}
}
运行结果:
-979369984
94371840
94371840

方法二:

public class Demo01 {
public static void microAdd(long x,long y,int m){
for(int i=1;i<=m;i++){
y -= x; // 吃掉x个y
if(i%30) x *= 2; // 每隔3分钟x分裂一次
if(i%2
0) y *= 2; // 每隔2分钟y分裂一次
}
System.out.println(y);
}
public static void main(String[] args){
microAdd(10,89,60);
microAdd(10,90,60);
}
}

运行结果:
-979369984
94371840
结果如果是负数应置为0!!

23.信用卡号校验

当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,
因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证通过。
该校验的过程:
1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。
2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。
3、将奇数位总和加上偶数位总和,结果应该可以被10整除。
例如,卡号是:5432123456788881
则奇数、偶数位(用红色标出)分布:5432123456788881
奇数位和=35
偶数位乘以2(有些要减去9)的结果:1 6 2 6 1 5 7 7,求和=35。
最后35+35=70 可以被10整除,认定校验通过。
请编写一个程序,从键盘输入卡号,然后判断是否校验通过。通过显示:“成功”,否则显示“失败”。
比如,用户输入:356827027232780
程序输出:成功
package Question20_29;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Question23 {
public static String judge(String s) {
int count=1;
int sum=0;
for (int i = s.length()-1; i >=0 ; i–,count++) {
if(count%2==1){
sum+=(s.charAt(i)-‘0’);
}else {
sum+=(s.charAt(i)-‘0’)*2>=10?(s.charAt(i)-‘0’)*2-9:(s.charAt(i)-‘0’)*2;
}

	}
	if(sum%10==0){
		return "成功";
	}else {
		return "失败";
	}
}
public static void main(String[] args) {
	Scanner scanner=new Scanner(System.in);
	String s=scanner.nextLine();
	System.out.println(judge(s));
}

}
运行结果:
输入卡号:5432123456788881
成功

方法二:
public class Card {
public static int getOddSum(String str){
int[] a;
int sum=0;
int length=str.length();
a=new int[(length+1)/2];
int j=0;
System.out.println(“奇数位为:”);
for(int i=length-1;i>=0;i=i-2){
System.out.println(str.substring(i, i+1));
a[j++]=Integer.parseInt(str.substring(i, i+1));
}
for(int i=0;i<a.length;i++){sum+=a[i];}
System.out.println(sum);
return sum;
}
public static int getEvenSum(String str){
int[] a;
int sum=0;
int length=str.length();
a=new int[length/2];
int j=0;
System.out.println(“偶数位为:”);
for(int i=length-2;i>=0;i=i-2){
System.out.println(str.substring(i, i+1));
a[j++]=Integer.parseInt(str.substring(i, i+1));
}
for(int i=0;i<a.length;i++){sum=sum+(a[i]*2)%9;}
System.out.println(sum);
return sum;
}
public static void main(String args[]){
Scanner scanner=new Scanner(System.in);
System.out.println(“please input your name:”);
String str=scanner.next();
if((Card.getOddSum(str)+Card.getEvenSum(str))%10==0)System.out.println(“成功!”);
else System.out.print(“失败!”);
}
}

方法三:
import java.util.Scanner;
public class Demo10 {
public static int calc(String s){
int odd = 0;
int even = 0;
int t = 0;
char[] c = s.toCharArray();
if(c.length%20){ // 如果位数为偶数个,则第一个数从偶数开始算起
for(int i=0;i<c.length;i++){
t = c[i]-‘0’;
if(i%2!=0){
odd += t;
}else{ // 第一个数加入到偶数
if(t2>=10){
even += t
2-9;
}else{
even += t*2;
}
}
}
}else{ // 如果位数为奇数个,则第一个数从奇数开始算起
for(int i=0;i<c.length;i++){
t = c[i]-‘0’;
if(i%2
0){ // 第一个数加入到奇数
odd += t;
}else{
if(t2>=10){
even += t
2-9;
}else{
even += t*2;
}
}
}
}
return odd+even; // 返回奇数位总和加上偶数位总和
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.print(“输入卡号:”);
String s = scan.nextLine();
if(calc(s)%10==0){ // 结果可以被10整除
System.out.println(“成功”);
}else{
System.out.println(“失败”);
}
}
}

运行结果:
输入卡号:5432123456788881
成功

24.输入日期

从键盘输入一个日期,格式为yyyy-M-d
要求计算该日期与1949年10月1日距离多少天
例如:
用户输入了:1949-10-2
程序输出:1
用户输入了:1949-11-1
程序输出:31
package Question20_29;
import java.util.Scanner;
publicclass Question24MustRemember {
publicstaticintdayOfYear[]={365,366};//平年365天,闰年366天
publicstaticintdayOfMonth[][]={
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}
};
publicstaticint dayOfYearIndex(int year){ //根据是否是闰年来给出dayOfYear的数组的下标
if((year%40&&year%100!=0)||year%4000){
return 1;
}
return 0;
}
publicstaticint dayApartFromTheBrginOfYear(int year,int month,int day){//计算month月day日是year年的第几天
int days=day;
for (int i = 1; i < month; i++) {
days+=dayOfMonth[dayOfYearIndex(year)][i];
}
return days;
}
publicstaticint apartDays(String startDayString,String endDayString ) {
String s1[]=startDayString.split(“-”);
String s2[]=endDayString.split(“-”);
int days=0;
intflag;
int startYear=Integer.parseInt(s1[0]);
int endYear=Integer.parseInt(s2[0]);
int startMonth=Integer.parseInt(s1[1]);
int endMonth=Integer.parseInt(s2[1]);
int startDay=Integer.parseInt(s1[2]);
int endDay=Integer.parseInt(s2[2]);
for (int i = startYear; i < endYear; i++) {
days+=dayOfYear[dayOfYearIndex(i)];
}
days+=dayApartFromTheBrginOfYear(endYear,endMonth,endDay);
days-=dayApartFromTheBrginOfYear(startYear,startMonth,startDay);
return days;
}
publicstaticvoid main(String[] args) {
Scanner scanner=new Scanner(System.in);
String startDayString=“1949-10-01”;
String endDayString=scanner.nextLine();
System.out.println(apartDays(startDayString, endDayString));
}
}
运行结果:
输入日期格式为:(1949-10-2)
输入第一个日期:1949-10-2
输入第二个日期:1949-11-2
1949-10-2 到 1949-11-2
距离31天

方法二:
import java.util.Arrays;
import java.util.Scanner;
public class Demo09 {
static int[][] days = { // 定义平年days[0]和闰年days[1]
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}};

// 字符串转换 整数   
public static int[] conversion(String s) {  
    String[] ss = s.split("\\-");  
    int[] t = new int[3];  
    t[0] = Integer.parseInt(ss[0]);  
    t[1] = Integer.parseInt(ss[1]);  
    t[2] = Integer.parseInt(ss[2]);  
    return t;  
}  
// 计算任意一年内的总天数 (是365还是366)   
public static int calcDay(int y,int m,int d){  
    int sum = d;    // 每一年的总天数 (初始化为最后一个月的天数)   
    int i = 0;      // 平年下标为 0   
    if((y%4==0&&y%100!=0)||(y%400==0)) i = 1; // 闰年下标为 1   
    for(int j=0;j<m;j++){  
        sum += days[i][j];  
    }  
    return sum;  
}  
// 判断是否交换输入的两个日期 (日期小者放前)   
public static void isSwap(int[] o,int[] n){  
    if(o[0]>n[0]){   // 日期内容交换   
        for(int i=0;i<o.length;i++){  
            int t = o[i];  
            o[i] = n[i];  
            n[i] = t;  
        }  
    }  
}  
// 输出   
public static String p(int[] s){  
    StringBuffer sb = new StringBuffer();  
    for(int i=0;i<s.length-1;i++){  
        sb.append(s[i]+"-");  
    }  
    sb.append(s[s.length-1]);  
    return sb.toString();  
}  
// 计算总天数   
public static int calc(int[] o, int[] n) {  
    int sum;  
    if(n[0]==o[0]){ // 如果年份相等,侧直接计算天数   
        sum = calcDay(n[0],n[1],n[2])-calcDay(o[0],o[1],o[2]);  // 大的日期天数-小的日期天数   
    }else{  
        sum = calcDay(o[0],12,31)-calcDay(o[0],o[1],o[2]);  // 得到第一年日期到下一年开始的天数   
        for(int i=o[0]+1;i<n[0];i++){    // 中间的每年天数 (不包含第一年和最后一年)   
            sum += calcDay(i,12,31);  
        }  
        sum += calcDay(n[0],n[1],n[2]); // 加上最后一年的天数   
    }  
    return sum;  
}  
public static void main(String[] args){

// int[] o = conversion(“1949-10-2”);
Scanner scan = new Scanner(System.in);
System.out.print(“输入日期格式为:(1949-10-2)\n输入第一个日期:”);
int[] o = conversion(scan.nextLine());
System.out.print(“输入第二个日期:”);
int[] n = conversion(scan.nextLine());
int sum = 0; // 总和
isSwap(o,n); // 如果o日期小于n日期,侧交换
sum = calc(o, n); // 计算总天数
System.out.println(p(o)+” 到 “+p(n)+”\n距离”+sum+“天”);
}
}

运行结果:
输入日期格式为:(1949-10-2)
输入第一个日期:1949-10-2
输入第二个日期:1949-11-2
1949-10-2 到 1949-11-2
距离31天

25.顺时针螺旋填入

从键盘输入一个整数(1~20)
则以该数字为矩阵的大小,把1,2,3…n*n 的数字按照顺时针螺旋的形式填入其中。例如:
输入数字2,则程序输出:
1 2
4 3
输入数字3,则程序输出:
1 2 3
8 9 4
7 6 5
输入数字4,则程序输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
package Question20_29;
import java.util.Scanner;
publicclass Question25 {
publicstaticvoid print(int[][] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
System.out.printf(“%4d”,array[i][j]);
}
System.out.println();
}
}
publicstaticvoid main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int array[][]=newint[n][n];
int startIndex=0,endIndex=n-1,count=1,e=0;
while (e<=n/2) {
for (int i = startIndex; i <= endIndex; i++) {
array[e][i]=count++;
}
for (int i = startIndex+1; i <= endIndex; i++) {
array[i][n-1-e]=count++;
}
for (int i = endIndex-1; i>=startIndex; i–) {
array[n-1-e][i]=count++;
}
for (int i = endIndex-1; i>startIndex; i–) {
array[i][e]=count++;
}

		startIndex++;
		endIndex--;
		e++;
	}
	print(array);
}

}
运行结果:
输入一个整数:4
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7

方法二:
import java.util.Scanner;
public class Demo08 {
public static void show(int[][] m) {
for(int[] x:m){
for(int y:x){
System.out.print(y+“\t”);
}
System.out.println(“”);
}
}
// 顺时针螺旋
public static int[][] helix(int n) {
int[][] m = new int[n][n]; // 产生空矩阵
int t = nn; // 填充矩阵从1到nn个数
int i = 0; // 填充数字的位置(行下标)
int j = 0; // 填充数字的位置(列下标)
int start = 0; // 每填充一圈时用的边界(左上)
int end = n; // 每填充一圈时用的边界(右下)
int x = 0; // 填充左侧一竖列数字时用的起始位置(行下标)
int y = 0; // 填充左侧一竖列数字时用的起始位置(列下标)
int count = 0; // 标记那段程序执行,那段程序不执行
for(int s=1;s<=t;s++){
if(istart&&j<end){ // 如果是第一行
m[i][j++] = s; // 填充第一行
}else if(i<end-1&&count<1){ // count
0时处理
j = end-1; // 列设置为右边界
i++; // 行下标 下移
}
if(i>start&&i<end){
if(j>start){
if(iend-1){ // 到下边界了
m[i][j–] = s; // 填充下边界
}else{
m[i][j] = s; // 填充右侧一竖列数字
}
}else if(count
0){ // 只当count0 时执行一次
m[i][j] = s; // 填充到了左下角的元素
i–; // 开始从下向上填充左侧元素(行坐标上移)
x = i; // 用新的下标x来填充左侧 (行下标)
y = j; // 用新的下标y来填充左侧 (列下标)
count++;
}else if(x>start&&y<end){
m[x–][y] = s; // 填充左侧
}else if(x
start){ // 如果外圈填充完毕
s–; // 接下来填充的数字放到下一的内圈里(抵消循环的s++)
start++; // 左上角边界向内收缩 1
end = –n; // 右下角边界向内收缩 1
i = start; // 按边界的位置开始填充内圈(行下标)
j = start; // 按边界的位置开始填充内圈(列下标)
x = i; // 填充左侧一竖列数字时用的起始位置(行下标)
y = j; // 填充左侧一竖列数字时用的起始位置(列下标)
count = 0; // 恢复执行程序段的标记
}
}
}
return m; // 返回矩阵
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.print(“输入一个整数:”);
int n = scan.nextInt(); // 输入 n
int[][] m = helix(n); // 矩阵大小为n*n
show(m); // 输出矩阵
}
}
自己写的,用到的控制变量比较多,所以程序读起来容易混乱!
整体思路: (外圈实现:

  1. 从(左->右)填充第一行
    2.从(上->下)填充右侧一列
    3.从(右->左)填充最后一行
    4.从(下->上)填充左侧一列
    只要最外圈能做出来,内圈同理,调整变量就可以了)
    方法三:
    publicclassDemo08_two {
    publicstaticvoid show(int[][] m) {
    for (int[] x : m) {
    for (int y : x) {
    System.out.print(y + “\t”);
    }
    System.out.println(“”);
    }
    }
    publicstaticvoid helix(int n, int b, int[][] a) {
    int i;
    int j;
    int k;
    for (i = 0; i < n / 2; i++) {
    for (j = i; j < n – i; j++)
    /* 四个循环按不同的方向进行 /
    a[i][j] = ++b;
    for (k = i + 1, j–; k < n – i; k++)
    a[k][j] = ++b;
    for (j = –k, j–; j >= i; j–)
    a[k][j] = ++b;
    for (k–; k > i; k–)
    a[k][i] = ++b;
    }
    if (n % 2 != 0) /
    如果是单数的话,要加上最大的那个数放在中间 */
    a[i][i] = ++b;
    }
    publicstaticvoid main(String[] args) {
    Scanner scan = newScanner(System.in);
    int i, j, k, n, b = 0;
    System.out.print(“输入一个整数:”);
    n = scan.nextInt();
    int[][] a = newint[n][n];
    helix(n, b, a);
    show(a);
    }
    }
    运行结果:
    输入一个整数:4
    1 2 3 4
    12 13 14 5
    11 16 15 6
    10 9 8 7

26.Playfair密码

一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),
然后与字母表中其他字母一起填入至一个5×5的方阵中,填入方法如下:
1.首先按行填入密钥串。
2.紧接其后,按字母序按行填入不在密钥串中的字母。
3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。
如果密钥为youandme,则该方阵如下:
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
在加密一对字母时,如am,在方阵中找到以这两个字母为顶点的矩形(红色字体):
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
这对字母的加密字母为该矩形的另一对顶点,如本例中为ob。
请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。
另外有如下规定:
1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在正方形中”如z”,则不变换,直接放入加密串中;
4、如果字母对出现在方阵中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为am,则该矩形的另一对顶点字母中,
与a同行的字母应在前面,在上例中应是ob;同样若待变换的字母对为ta,则变换后的字母对应为wo;
6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。
解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。
要求输入形式如下:
从控制台输入两行字符串,第一行为密钥单词(长度小于等于25),第二行为待加密字符串(长度小于等于50),
两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。
在标准输出上输出加密后的字符串。
例如,若输入:
youandme
welcometohangzhou
则表示输入的密钥单词为youandme,形成的正方形如上所示;待加密字符串为welcometohangzhou。
在正方形中可以找到以第一对字母we为顶点的矩形,对应另一对顶点字母为vb,因此加密后为vb,
同理可找到与字母对lc,et,oh,ho对应的顶点字母对。而字母对om位于上述正方形中的同一列,
所以直接以颠倒这两个字母来加密,即为mo,字母对an同理。字母对gz中的z不在上述正方形中,
因此原样放到加密串中。最后剩一个字母u也原样输出。
因此输出的结果为:
vbrmmomvugnagzguu
vbrmmomvugnagzguu
vbrmmomvugnagzguu
要求考生把所有类写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。请不要使用package语句。
另外,源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。

package Question20_29;
import java.util.Scanner;
import java.util.Vector;
public class Question26 {
public static char initArray(char[][] array, String pair) {
Vectorvector=new Vector();
for (char i = ‘a’; i <=‘z’; i++) {
vector.add(i);
}
for (int i = 0; i < pair.length(); i++) {
vector.remove((Character)pair.charAt(i));
array[i/5][i%5]=pair.charAt(i);
}
for (int i = 0,j=pair.length() ; i < vector.size()-1; i++,j++) {
array[j/5][j%5]=vector.elementAt(i);
}
return vector.elementAt(vector.size()-1);
}
public static String passwordAfterChange(char[][] array,String password,char unUsedch) {
StringBuffer sb=new StringBuffer();
for (int i = 0; i < password.length(); i+=2) {
if(i+1<password.length()){
if(password.charAt(i)==unUsedch||password.charAt(i+1)==unUsedch){//如果一对字母中有一个字母不在正方形中”如z”,则不变换,直接放入加密串中
sb.append(password.charAt(i));
sb.append(password.charAt(i+1));
}else if (password.charAt(i)==password.charAt(i+1)) {//如果一对字母中的两个字母相同,则不变换,直接放入加密串中
sb.append(password.charAt(i));
sb.append(password.charAt(i+1));
}else {
int ch1i=0,ch1j=0,ch2i=0,ch2j = 0;
for (int j = 0; j < array.length; j++) {
for (int j2 = 0; j2 < array.length; j2++) {
if(array[j][j2]password.charAt(i)){
ch1i=j;ch1j=j2;
}else if(array[j][j2]password.charAt(i+1)){
ch2i=j;ch2j=j2;
}
}
}
if(ch1i
ch2i||ch1j
ch2j){//如果字母对出现在方阵中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih
sb.append(password.charAt(i+1));
sb.append(password.charAt(i));
}else {
sb.append(array[ch1i][ch2j]);
sb.append(array[ch2i][ch1j]);
}

			}
		}else {//一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中
			sb.append(password.charAt(i));
		}
	}
	return sb.toString();
}
public static void main(String[] args) {
	char array[][]=new char[5][5];
	Scanner scanner = new Scanner(System.in);
	String pair = scanner.nextLine();
	String password=scanner.nextLine();
	char unUsedch=initArray(array, pair);
	System.out.println(passwordAfterChange(array, password, unUsedch));
}

}
运行结果:
输入密钥单词:youandme
输入待加密字符:welcometohangzhou
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
加密结果:vbrmommvugnagzguu
解密结果:welcometohangzhou

方法二:
import java.util.Scanner;
public class Demo09 {
static char a = ‘a’;
// 返回不包含在key里的元素
public static char contains(String k){
if(k.indexOf(a)>0){ // 如果 k 包含 c 则 a++ 再进行测试
a++;
contains(k);
}
return a; // 返回不包含在key里的元素
}
// 显示矩阵
public static void show(char[][] m){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
System.out.print(” “+m[i][j]);
}
System.out.println();
}
}
// 完成矩阵添加元素
public static void fillmatrix(String key, char[][] m) {
int len = 0;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(len<key.length()){
m[i][j] = key.charAt(len);
len++;
}else{ // 添加 (a~z在key里不包含)的元素
m[i][j] = contains(key);
a++;
}
}
}
}
// 待加密的字符串分对(2个字符一对)
public static String[] pair(String str){
String[] ss = new String[(str.length()+1)/2];
StringBuffer sb = new StringBuffer(str);
int i = 0;
while(sb.length()!=0){
if(sb.length()<=1){
ss[i] = sb.toString();
break;
}else{
ss[i++] = sb.substring(0,2);
sb.delete(0, 2);
}
}
return ss;
}
public static String find(String ss,char[][] m){
char[] c = ss.toCharArray();
if(c.length==1) return ss; // 如果是一个字符,则直接返回
int count = 0; // 统计c里的两个字符中否都存在
int[] f = new int[4]; // 保存下标
StringBuffer sb = new StringBuffer();
for(int i=0;i<m.length;i++){
for(int j=0;j<m[i].length;j++){
if(m[i][j]==c[0]){
f[0] = i; // f[0,1]保存第一个字符的位置
f[1] = j;
count++; // 存在加1
}else if(m[i][j]==c[1]){
f[2] = i; // f[0,1]保存第二个字符的位置
f[3] = j;
count++; // 存在加1
}
}
}
if(count!=2) return ss; //count!=2说明有一个字符在矩阵里不存在
sb.append(m[f[0]][f[3]]); // 添加加密后的第一个字符
sb.append(m[f[2]][f[1]]); // 添加加密后的第二个字符
return sb.toString();
}
// 加密
public static String encry(String str,char[][] m){
StringBuffer sb = new StringBuffer();
String[] ss = pair(str);
for(int i=0;i<ss.length;i++){
sb.append(find(ss[i],m));
}
return sb.toString();
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.print(“输入密钥单词:”);
String key = scan.nextLine();
System.out.print(“输入待加密字符:”);
String str = scan.nextLine();
char[][] m = new char[5][5];
fillmatrix(key, m); // 完成矩阵添加元素
show(m); // 显示矩阵
String e = encry(str,m); // 加密
System.out.println(“加密结果:”+e); // 输出加密后的字符串
String d = encry(e,m); // 解密
System.out.println(“解密结果:”+d); // 输出加密后的字符串
}
}

运行结果:
输入密钥单词:youandme
输入待加密字符:welcometohangzhou
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
加密结果:vbrmommvugnagzguu
解密结果:welcometohangzhou

27.漏掉的账目明细

某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。
如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
如果有多种可能,则输出所有可能的情况。
我们规定:用户输入的第一行是:有错的总金额。
接下来是一个整数n,表示下面将要输入的明细账目的条数。
再接下来是n行整数,分别表示每笔账目的金额。
要求程序输出:所有可能漏掉的金额组合。每个情况1行。金额按照从小到大排列,中间用空格分开。
比如:
用户输入:
6
5
3
2
4
3
1
表明:有错的总金额是6;明细共有5笔。
此时,程序应该输出:
1 3 3
1 2 4
3 4
为了方便,不妨假设所有的金额都是整数;每笔金额不超过1000,金额的明细条数不超过100。

package Question20_29;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Vector;
import java.util.concurrent.PriorityBlockingQueue;
import javax.swing.text.AbstractDocument.BranchElement;
public class Question27 {
public static String elementOfPriorityBlockingQueue(int array[],boolean used[]) {
PriorityBlockingQueuepriorityBlockingQueue=new PriorityBlockingQueue();
for (int i = 0; i < used.length; i++) {
if(used[i]true){
priorityBlockingQueue.add(array[i]);
}
}
StringBuffer sb=new StringBuffer();
while (!priorityBlockingQueue.isEmpty()) {
sb.append(priorityBlockingQueue.poll());
}
return sb.toString();
}
public static void exeForward(PriorityBlockingQueuepriorityBlockingQueue,int array[],boolean used[],int index,int sum,int tSum) {
if(sum>tSum){
return;
}
if(sum
tSum){
String string=elementOfPriorityBlockingQueue(array, used);
if(!priorityBlockingQueue.contains(string)){
priorityBlockingQueue.add(string);
}
return;
}
if(index<=array.length-1){
for (int i = 0; i <=1; i++) {
used[index]=(i0?false:true);
sum+=array[index]*i;
exeForward(priorityBlockingQueue,array, used, index+1, sum, tSum);
sum-=array[index]*i;
used[index]=(i
1?false:true);
}
}else {
return;
}
}
public static void main(String[] args) {
int tSum;
int n;
Vectorvector=new Vector();
Scanner scanner=new Scanner(System.in);
PriorityBlockingQueuepriorityBlockingQueue=new PriorityBlockingQueue();
tSum=scanner.nextInt();
n=scanner.nextInt();
int array[]=new int[n];
boolean used[]=new boolean[n];
tSum*=(-1);
for (int i = 0; i < n; i++) {
array[i]=scanner.nextInt();
tSum+=array[i];
}
exeForward(priorityBlockingQueue,array, used, 0, 0, tSum);
while (!priorityBlockingQueue.isEmpty()) {
String string=priorityBlockingQueue.poll();
for (int i = 0; i < string.length(); i++) {
System.out.print(string.charAt(i));
if(i!=string.length()-1){
System.out.print(” “);
}
}
System.out.println();
}
}
}
运行结果:
6
5
3
2
4
3
1
输出结果:
3 4
1 3 3
1 2 4

方法二:

/*

  • 某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。
  • 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
  • 如果有多种可能,则输出所有可能的情况。
  • 我们规定:用户输入的第一行是:有错的总金额。
  • 接下来是一个整数n,表示下面将要输入的明细账目的条数。
  • 再接下来是n行整数,分别表示每笔账目的金额。
  • 要求程序输出:所有可能漏掉的金额组合。每个情况1行。金额按照从小到大排列,中间用空格分开。
  • 比如:
  • 用户输入:
    6
    5
    3
    2
    4
    3
    1
    表明:有错的总金额是6;明细共有5笔。
    此时,程序应该输出:
    1 3 3
    1 2 4
    3 4
    为了方便,不妨假设所有的金额都是整数;每笔金额不超过1000,金额的明细条数不超过100。
    */
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.LinkedHashSet;
    import java.util.List;
    import java.util.Scanner;
    import java.util.Set;

public class Demo08 {
static Set<List> sets = new LinkedHashSet<List>(); // 保存记录
// 得到漏掉的总金额
public static int sum(int[] d){
int leak = 0;
for(int i=0;i<d.length;i++){
leak += d[i];
}
return leak;
}
// 修改b元素+1进位
public static void modify(int[] b){
b[b.length-1]++;
for(int i=b.length-1;i>0;i–){
if(b[i]>1){
b[i] = 0;
b[i-1]++;
}
}
}
// 检测b是否全111111…
public static boolean check(int[] b){
boolean flag = true;
for(int i=0;i<b.length;i++){
if(b[i]0){
flag = false;
break;
}
}
return flag;
}
public static void calc(int le,int[] d,int[] b){
if(check(b)){
return;
}
int sum = 0;
for(int i=d.length-1;i>=0;i–){
if(b[i]!=0){
sum += d[i];
}
}
if(sum
le){
List lis = new ArrayList();
for(int i=0;i<d.length;i++){
if(b[i]!=0){
lis.add(d[i]);
}
}
sets.add(lis);
//lis.clear();
}
modify(b);
calc(le,d,b);
}
// 输出结果
public static void print(){
Iterator<List> iter = sets.iterator();
while(iter.hasNext()){
Iterator iter2 = iter.next().iterator();
while(iter2.hasNext()){
System.out.print(iter2.next()+” “);
}
System.out.println();
}
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int err = scan.nextInt();
int n = scan.nextInt();
int[] d = new int[n];
for(int i=0;i<n;i++){
d[i] = scan.nextInt();
}
Arrays.sort(d);
int le = sum(d) – err; // 得到漏掉的总金额
int[] b = new int[d.length]; // 初始为全零 作为标记,记录数字是否使用 0为未使用 1为已经使用
calc(le,d,b);
System.out.println(“输出结果:”);
print();
}
}

运行结果:
6
5
3
2
4
3
1
输出结果:
3 4
1 3 3
1 2 4

28.制作表格

在中文Windows环境下,控制台窗口中也可以用特殊符号拼出漂亮的表格来。
比如:
┌─┬─┐
│││
├─┼─┤
│││
└─┴─┘
其实,它是由如下的符号拼接的:
左上 = ┌
上 = ┬
右上 = ┐
左 = ├
中心 = ┼
右 = ┤
左下= └
下 = ┴
右下 = ┘
垂直 = │
水平 = ─
本题目要求编写一个程序,根据用户输入的行、列数画出相应的表格来。
例如用户输入:
3 2
则程序输出:
┌─┬─┐
│││
├─┼─┤
│││
├─┼─┤
│││
└─┴─┘
用户输入:
2 3
则程序输出:
┌─┬─┬─┐
││││
├─┼─┼─┤
││││
└─┴─┴─┘
要求考生把所有类写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。相关的工程文件不要拷入。请不要使用package语句。
另外,源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
package Question20_29;
import java.util.Scanner;
publicclass Question28 {
publicstaticvoid main(String[] args) {
Scanner scanner=new Scanner(System.in);
int hang=scanner.nextInt(),lie=scanner.nextInt();
for (int i = 0; i < hang; i++) {
if(i==0){
System.out.print(“┌─”);
for (int j = 0; j < lie-1; j++) {
System.out.print(“┬─”);
}
System.out.println(“┐”);
for (int j = 0; j < lie; j++) {
System.out.print(“│ “);
}
System.out.println(“│”);
}else {
System.out.print(“├─”);
for (int j = 0; j < lie-1; j++) {
System.out.print(“┼─”);
}
System.out.println(“┤”);

			for (int j = 0; j < lie; j++) {
				System.out.print("│ ");
			}
			System.out.println("│");
		}
	}
	System.out.print("└─");
	for (int j = 0; j < lie-1; j++) {
		System.out.print("┴─");
	}
	System.out.println("┘");
	//System.out.print("┌");System.out.print("─");System.out.print("┬");System.out.print("─");System.out.print("┐");
}

}
运行结果:
请输出两个数,行和列 ,例: 3 4
3 4
┌─┬─┬─┬─┐
│││││
├─┼─┼─┼─┤
│││││
├─┼─┼─┼─┤
│││││
└─┴─┴─┴─┘
方法二:
import java.util.Scanner;
public class WinGraph {
//使用字符数组存放基本图形
public static char[] gr={‘┌’,‘┬’,‘┐’,‘├’,‘┼’,‘┤’,‘└’,‘┴’,‘┘’,‘│’,‘─’};
public static void paintGraph(int row,int col){
//打印表格上边框
System.out.print(gr[0]);
System.out.print(gr[10]);
for(int i=1;i<col;i++){
System.out.print(gr[1]);
System.out.print(gr[10]);
}
System.out.println(gr[2]);
//打印表格中间部分
for(int i=0;i<=col;i++){
System.out.print(gr[9]);
System.out.print(” “);
}
System.out.println();
for(int i=1;i<row;i++){
System.out.print(gr[3]);
System.out.print(gr[10]);
for(int j=1;j<col;j++){
System.out.print(gr[4]);
System.out.print(gr[10]);
}
System.out.println(gr[5]);
for(int k=0;k<=col;k++){
System.out.print(gr[9]);
System.out.print(” “);
}
System.out.println();
}
//打印表格下边框
System.out.print(gr[6]);
System.out.print(gr[10]);
for(int i=1;i<col;i++){
System.out.print(gr[7]);
System.out.print(gr[10]);
}
System.out.println(gr[8]);
}
//main 方法
public static void main(String args[]){
int row, col;
System.out.println(“请输入表格列数 :”);
Scanner sc=new Scanner(System.in);
row=sc.nextInt();
System.out.println(“请输入表格列数 :”);
col=sc.nextInt();
paintGraph(row,col);
}
}

方法三:
import java.util.Scanner;
public class Demo07 {
// 输出中间全部都是竖杠的行
public static void middle(int j){
for(int i=0;i<j;i++){
System.out.print(“│ “);
}
System.out.println(“│”);
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“请输出两个数,行和列:”);
int row = scan.nextInt();
int col = scan.nextInt();
for(int i=0;i<row;i++){
for(int j=0;j<=col;j++){
if(i0){ // 输出第一行
if(j
0){
System.out.print(“┌─”);
}else if(j>0&&j<col){
System.out.print(“┬─”);
}else{
System.out.println(“┐”);
middle(col);
}
}else if(irow){ // 输出最后一行
if(j
0){
System.out.print(“└─”);
}else if(j>0&&j<col){
System.out.print(“┴─”);
}else{
System.out.println(“┘”);
}
}else{ // 输出中间行
if(j==0){
System.out.print(“├─”);
}else if(j>0&&j<col){
System.out.print(“┼─”);
}else{
System.out.println(“┤”);
middle(col);
}
}
}
}
}
}
运行结果:
请输出两个数,行和列 ,例: 3 4
3 4
┌─┬─┬─┬─┐
│ │ │ │ │
├─┼─┼─┼─┤
│ │ │ │ │
├─┼─┼─┼─┤
│ │ │ │ │
└─┴─┴─┴─┘

29.迷宫走法

迷宫问题
对于走迷宫,人们提出过很多计算机上的解法。深度优先搜索、广度优先搜索是使用最广的方法。生活中,人们更愿意使用“紧贴墙壁,靠右行走”的简单规则。
下面的代码则采用了另一种不同的解法。它把走迷宫的过程比做“染色过程”。
假设入口点被染为红色,它的颜色会“传染”给与它相邻的可走的单元。
这个过程不断进行下去,如果最终出口点被染色,则迷宫有解。
仔细分析代码中的逻辑,填充缺少的部分。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

class Cell{		// 单元格
	introw;	// 哪行
	intcol;	// 哪列
	Cell from;	// 开始点
	public Cell(int row,int col,Cell from){
		this.row = row;
		this.col = col;
		this.from = from;
	}
}
publicclassT04 {
	staticchar[][] maze = {
			{'#','#','#','#','B','#','#','#','#','#','#','#'},
			{'#','#','#','#','.','.','.','.','#','#','#','#'},
			{'#','#','#','#','.','#','#','#','#','.','.','#'},
			{'#','.','.','.','.','#','#','#','#','#','.','#'},
			{'#','.','#','#','#','#','#','.','#','#','.','#'},
			{'#','.','#','#','#','#','#','.','#','#','.','#'},
			{'#','.','#','#','.','.','.','.','.','.','.','#'},
			{'#','.','#','#','.','#','#','#','.','#','.','#'},
			{'#','.','.','.','.','#','#','#','.','#','.','#'},
			{'#','#','.','#','.','#','#','#','.','#','.','A'},
			{'#','#','.','#','#','#','.','.','.','#','#','#'},
			{'#','#','#','#','#','#','#','#','#','#','#','#'}
	};
	// 显示迷宫
	publicstaticvoid show(){
		for(int i=0;i<maze.length;i++){
			for(int j=0;j<maze[i].length;j++){
				System.out.print(" "+maze[i][j]);
			}
			System.out.println();
		}
	}
	// 染色
	publicstatic Cell colorCell(Set<Cell> from,Set<Cell> desc){
		Iterator<Cell> iter = from.iterator();
		while(iter.hasNext()){
			Cell a = iter.next();
			Cell c[] = new Cell[4];
			c[0] = new Cell(a.row-1,a.col,a); // 向上走
			c[1] = new Cell(a.row+1,a.col,a); // 向下走
			c[2] = new Cell(a.row,a.col-1,a); // 向左走
			c[3] = new Cell(a.row,a.col+1,a); // 向右走
			for(int i=0;i<4;i++){
				if(c[i].row<0 || c[i].row>=maze.length) continue;
				if(c[i].col<0 || c[i].col>=maze[0].length) continue;
				
				char x = maze[c[i].row][c[i].col];	// 取得单元格对应字符
				if(x=='B') return a;
				if(x=='.'){
					maze[c[i].row][c[i].col] = '?';	// 染色
					desc.add(c[i]);
				}
			}
		}
		returnnull;
	}
	// 
	publicstaticvoid resolve(){
		Set<Cell> set = new HashSet<Cell>();
		set.add(new Cell(9,11,null));
		for(;;){
			Set<Cell> set1 = new HashSet<Cell>();
			// 出口  a.from.from.from.....<-(set.get(0).from)==null<-入口
			Cell a = colorCell(set,set1);	
			if(a!=null){	// 找到解
				System.out.println("找到解!");
				while(a!=null){	// 当前a里包含a.from 一直往前推
					maze[a.row][a.col] = '+';	// 染色路径
					a = a.from;
				}
				break;
			}
			if(set1.isEmpty()){	// 遍历所以一直到没有路走,这时 set1为空
				System.out.println("无解!");
				break;
			}
			set = set1;	// 向里边
		}
	}
	publicstaticvoid main(String[] args){
		show();
		resolve();
		show();
	}
}

运行结果:

# # # # B # # # # # # #
 # # # # . . . . # # # #
 # # # # . # # # # . . #
 # . . . . # # # # # . #
 # . # # # # # . # # . #
 # . # # # # # . # # . #
 # . # # . . . . . . . #
 # . # # . # # # . # . #
 # . . . . # # # . # . #
 # # . # . # # # . # . A
 # # . # # # . . . # # #
 # # # # # # # # # # # #
找到解!
 # # # # B # # # # # # #
 # # # # + . . . # # # #
 # # # # + # # # # ? ? #
 # + + + + # # # # # ? #
 # + # # # # # ? # # ? #
 # + # # # # # ? # # ? #
 # + # # + + + + + + + #
 # + # # + # # # ? # + #
 # + + + + # # # ? # + #
 # # ? # ? # # # ? # + +
 # # ? # # # ? ? ? # # #
 # # # # # # # # # # # #

30. 5位黑洞数

任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到
一个最大的数:65432,一个最小的数23456。
求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则前边补0)。如此往复,数字会落入某个循环圈(称为数字黑洞)。
比如,刚才的数字会落入:[82962,75933, 63954, 61974]这个循环圈。
请编写程序,找到5位数所有可能的循环圈,并输出,每个循环圈占1行。
其中5位数全都相同则循环圈为[0],这个可以不考虑。循环圈的输出格式仿照:
[82962,75933, 63954, 61974]其中数字的先后顺序可以不考虑。

package Question30_39;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Scanner;
import java.util.Set;
public class Question30TooDifficultMustRemember{
public static int MaxSubMin(int n) {
StringBuffer sb=new StringBuffer(“”+n);
while (sb.length()<5) {
sb.insert(0, ‘0’);
}
char ch[]=(sb.toString()).toCharArray();
Arrays.sort(ch);
int max=(ch[4]-‘0’)*10000+(ch[3]-‘0’)*1000+(ch[2]-‘0’)*100+(ch[1]-‘0’)*10+ch[0]-‘0’;
int min=(ch[0]-‘0’)*10000+(ch[1]-‘0’)*1000+(ch[2]-‘0’)*100+(ch[3]-‘0’)*10+ch[4]-‘0’;
return max-min;
}
public static Set blackHole(int n) {
Set set=new LinkedHashSet();
set.add(n);
while(true){
n=MaxSubMin(n);
if(set.add(n)false){
SettSet=new LinkedHashSet();
for (Iterator iterator = set.iterator(); iterator.hasNext()???? {
Integer integer = (Integer) iterator.next();
if(integer
n){
break;
}else {
tSet.add(integer);
}
}
set.removeAll(tSet);
break;
}
}
return set;
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
// int n=scanner.nextInt();
Set<Set>set=new LinkedHashSet<>();
for (int i = 10000; i < 100000; i++) {
set.add(blackHole(i));
}

	for (Iterator iterator = set.iterator(); iterator.hasNext();) {
		Set<Integer> set2 = (Set<Integer>) iterator.next();
		System.out.println(set2);
	}
	
}

}
运行结果:
[0]
[74943, 62964, 71973, 83952]
[63954, 61974, 82962, 75933]
[53955, 59994]

方法二:
/*

  • 任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到
  • 一个最大的数:65432,一个最小的数23456。
  • 求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则前边补0)。
  • 如此往复,数字会落入某个循环圈(称为数字黑洞)。
    比如,刚才的数字会落入:[82962,75933, 63954, 61974]这个循环圈。
    请编写程序,找到5位数所有可能的循环圈,并输出,每个循环圈占1行。
    其中5位数全都相同则循环圈为[0],这个可以不考虑。循环圈的输出格式仿照:
    [82962,75933, 63954, 61974]
    其中数字的先后顺序可以不考虑。
    */
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.LinkedHashSet;
    import java.util.List;
    import java.util.Set;

public class BlackHole {
static Set<List> sets = new LinkedHashSet<List>();// 记录每个 循环圈
static int start = 0; // 记录循环圈的开始位置
// 得到最大的数
public static int max(String s){
char[] c = s.toCharArray();
Arrays.sort©;
StringBuffer sb = new StringBuffer(new String©);
return Integer.parseInt(sb.reverse().toString());
}
// 得到最小的数
public static int min(String s){
char[] c = s.toCharArray();
Arrays.sort©;
return Integer.parseInt(new String©);
}
// 补零
public static String fillZero(String s){
if(s.length()<5) return s; // 如果够五位的话,直接返回原数
StringBuffer sb = new StringBuffer(s);
int len = 5 – sb.length(); // 需要补 len 个零
for(int i=0;i<len;i++){
sb.insert(0, “0”);
}
return sb.toString();
}
// 查找是否有循环圈
public static boolean find(int n,List lis){
for(int i=0;i<lis.size();i++){
if(nlis.get(i)){
start = i; // 设置循环圈的开始
return true;
}
}
return false;
}
// 这个数字的五位是否都一样如:11111,22222,…
public static boolean same(int n){
char[] c = (“”+n).toCharArray();
char t = c[0];
for(int i=1;i<c.length;i++){
if(t!=c[i]){
return false;
}
}
return true;
}
// 判断是否在sets元素里重复
public static boolean contain(List tt){
boolean flag = false;
// 从sets头到尾扫描是是否包含tt元素组
Iterator<List> iter = sets.iterator();
while(iter.hasNext()){
if(iter.next().containsAll(tt)){
flag = true;
}
}
return flag;
}
// 输出循环圈
public static void print(){
Iterator<List> iter = sets.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
}
// 进入黑洞测试*********
public static void bl(int n,List lis){
String tt = fillZero(String.valueOf(n));
int a = max(tt); // 得到最大的数
int b = min(tt); // 得到最小的数
int c = a – b; // 得到五位数 结果
if(find(c,lis)){ // 找到循环圈
lis.add©; // 把最后一个元素添加进去
List temp = new ArrayList(); // 开辟新空间 并copy记录
temp.addAll(lis.subList(start, lis.size()-1));
if(!contain(temp)){ // 去重
sets.add(temp); // 记录一个循环圈
}
lis.clear(); // 清空
return ;
}
lis.add©;
bl(c,lis); // 递归探测
}
// 主函数
==========
public static void main(String[] args){
List lis = new ArrayList(); // 保存记录
for(int i=10000;i<99999;i++){
if(!same(i)) //去掉不符合条件的元素:如(11111,22222,…)
bl(i,lis); // 进入黑洞测试
}
print(); // 输出循环圈
}
}

运行结果:
[0]
[74943, 62964, 71973, 83952]
[63954, 61974, 82962, 75933]
[53955, 59994]

4位黑洞数
/* 数字黑洞
任意给定一个4位数(不能所有位都相同),比如:3278,重新组合出最大数:8723,
再重新组合出最小数:2378,相减,得到新的4位数(如不足则补0),重复这个过程,
最后必然得到一个数字:6174。这个现象被称为:数字黑洞。

下面的函数实现由给定的4位整数求出下一个整数的功能。请完善之。
*/
public class 数字黑洞 {
public static int f(int n) {
int N[] = new int[4];
for (int i = 0; i < 4; i++) {
N[3 – i] = n % 10;
n = n/10; // 填空
}
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3 – i; j++)
if (N[j] > N[j + 1]) {
int t = N[j + 1];
N[j + 1] = N[j];
N[j] = t;
}

    int n_min = 0;  
    for (int i = 0; i < 4; i++)  
        n_min = n_min * 10 + N[i];  
    int n_max = 0;  
    for (int i = 3; i >= 0; i--)  
        n_max = n_max * 10 + N[i];  

    return n_max - n_min;  
}  

public static void main(String[] args) {  
    int n = 3124;  
    System.out.println(f(n));  
}

}

31.基因牛的繁殖

张教授采用基因干预技术成功培养出一头母牛,三年后,这头母牛每年会生出1头母牛,
生出来的母牛三年后,又可以每年生出一头母牛。如此循环下去,请问张教授n年后有多少头母牛?
以下程序模拟了这个过程,请填写缺失的代码。
import java.util.ArrayList;
import java.util.List;
class Cow{
privateintage;
public Cow afterYear(){
age++;
returnage> 2 ? new Cow() : null; // 填空
}
publicstaticvoid showTotalCowNum(int n){
List list = new ArrayList();
list.add(new Cow());
for (int i = 0; i < n; i++) {
int cowCount = list.size();
for (int j = 0; j < cowCount; j++){
Cow cow = list.get(j).afterYear();
if (cow != null){
cow.afterYear(); // 填空
list.add(cow);
}
}
}
System.out.println(n + “年后,共有:” + list.size());
}
}
class Demo05{
publicstaticvoid main(String[] args){
Cow.showTotalCowNum(13);
}
}
运行结果:
13年后,共有:233

32.平面点最小距离

最近距离
已知平面上的若干点的位置,存入一个List中。现在需要计算所有这些点中,
距离最近的两个点间的最小距离。请补全缺失的代码。
把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
import java.util.ArrayList;
import java.util.List;
class MyPoint{
privatedoublex; // 横坐标
privatedoubley; // 纵坐标
public MyPoint(double x, double y){
this.x = x;
this.y = y;
}
publicstaticdouble distance(MyPoint p1, MyPoint p2){
double dx = p1.x – p2.x;
double dy = p1.y – p2.y;
return Math.sqrt(dxdx + dydy);
}
/*
lst中含有若干个点的坐标
返回其中距离最小的点的距离
*/
publicstaticdouble getMinDistance(List lst){
if(lst==null || lst.size()<2) return Double.MAX_VALUE;

	double r = Double.MAX_VALUE;
	MyPoint p0 = lst.remove(0);
	for(int i=0; i<lst.size(); i++){
		MyPoint p = lst.get(i);
		double d = MyPoint.distance(p0,p);
		if(d<r) r = d;	// 填空1
	}
	double d2 = getMinDistance(lst); // 填空2
	return d2 < r ? d2 : r;
}

}
class Demo04{
publicstaticvoid main(String[] args){
List list = new ArrayList() ;
list.add(new MyPoint(31,4));
list.add(new MyPoint(1,2));
list.add(new MyPoint(1,1));
list.add(new MyPoint(1,4));
System.out.println(MyPoint.getMinDistance(list));
}
}
运行结果:
1.0

33.字符串反转

/*
我们把“cba”称为“abc”的反转串。
求一个串的反转串的方法很多。下面就是其中的一种方法,代码十分简洁(甚至有些神秘),
请聪明的你通过给出的一点点线索补充缺少的代码。
把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
*/
publicclassDemo03 {
publicstatic String reverseString(String s){
if(s.length()<2||s==null) return s;
returnreverseString(s.substring(1))+s.charAt(0);
}
publicstaticvoid main(String[] args){
String s = “123456”;
String ss = reverseString(s);
System.out.println(ss);
}
}
运行结果:
654321

34.孪生素数

所谓孪生素数指的就是间隔为 2 的相邻素数,它们之间的距离已经近得不能再近了,
就象孪生兄弟一样。最小的孪生素数是 (3, 5),
在 100 以内的孪生素数还有 (5, 7), (11, 13), (17, 19), (29, 31),
(41, 43), (59, 61) 和 (71, 73),总计有 8 组。
但是随着数字的增大,孪生素数的分布变得越来越稀疏,寻找孪生素数也变得越来越困难。
那么会不会在超过某个界限之后就再也不存在孪生素数了呢?
孪生素数有无穷多对!这个猜想被称为孪生素数猜想,至今没有被严格证明。
但借助于计算机我们确实可以找到任意大数范围内的所有孪生素数对。
下面的代码求出了正整数n以内(不含n)的所有孪生素数对的个数。
比如,当n=100的时候,该方法返回8。试补全缺少的代码。
把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
class Demo02{
// 判断是否是素数
publicstaticboolean isPrime(int x){
for(int i=2; i<=x/2; i++){
if(x%i==0) return false;//填空
}
returntrue;
}
// 是否是孪生素数
publicstaticint twinPrimeNum(int n){
int sum = 0;
for(int i=2; i<n; i++){
if(isPrime(i) &&isPrime(i+2) && (i+2)<=n) sum++;//填空
}

	return sum; // 返回个数
}
publicstaticvoid main(String[] args){
	int n = 1000;
	System.out.println(twinPrimeNum(n));
}

}

35.圆周率与级数

我国古代数学家对圆周率方面的研究工作,成绩是突出的。三国时期的刘徽、南北朝时期的祖冲之都在这个领域取得过辉煌战绩。
有了计算机,圆周率的计算变得十分容易了。如今,人们创造了上百种方法求π的值。其中比较常用且易于编程的是无穷级数法。
π/4 = 1 – 1/3 + 1/5 – 1/7 + 1/9 – …
是初学者特别喜欢的一个级数形式,但其缺点是收敛太慢。
π/2 = 1 + 1/3 +1/32/5 + 1/32/53/7 + 1/32/53/74/9 + …
是收敛很快的一个级数方法。下面的代码演示了用这种方法计算π值。请填写缺失的代码部分。
把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
publicclassDemo01 {
publicstaticvoid main(String[] args){
double x = 1;
double y = 1;
int a = 1;
int b = 3;

	while(y>1e-15){
		y =  y*a/b;<span style="white-space:pre">	</span>// 填空
		x += y;
		a++;
		b += 2;
	}
	System.out.println(x*2);
}

}
36.最大5个数(测量到的工程数据)
[12,127,85,66,27,34,15,344,156,344,29,47,…]
这是某设备测量到的工程数据。
因工程要求,需要找出最大的5个值。
一般的想法是对它排序,输出前5个。但当数据较多时,这样做很浪费时间。
因为对输出数据以外的数据进行排序并非工程要求,即便是要输出的5个数字,
也并不要求按大小顺序,只要找到5个就可以。
以下的代码采用了另外的思路。考虑如果手里已经抓着5个最大数,再来一个数据怎么办呢?
让它和手里的数据比,如果比哪个大,就抢占它的座位,让那个被挤出来的再自己找位子,…
请分析代码逻辑,并推测划线处的代码。
答案写在“解答.txt”文件中
注意:只写划线处应该填的内容,划线前后的内容不要抄写。

import java.util.*;
publicclassDemo11_B23 {
publicstatic List max5(List lst) {
if (lst.size() <= 5)
return lst;
int a = lst.remove(lst.size() – 1); // 填空
List b = max5(lst);
for (int i = 0; i < b.size(); i++) {
int t = b.get(i);
if (a > t) {
lst.set(i, a); // 填空
a = t;
}
}
return b;
}
publicstaticvoid main(String[] args) {
List lst = new Vector();
lst.addAll(Arrays.asList(12, 127, 85, 66, 27, 34, 15, 344, 156, 344,
29, 47));
System.out.println(max5(lst));
}
}
运行结果:
[344, 344, 156, 127, 85]

37.祖冲之割圆法

南北朝时,我国数学家祖冲之首先把圆周率值计算到小数点后六位,比欧洲早了1100年!
他采用的是称为“割圆法”的算法,实际上已经蕴含着现代微积分的思想。
如图【1.jpg】所示,圆的内接正六边形周长与圆的周长近似。

多边形的边越多,接近的越好!我们从正六边形开始割圆吧。
如图【2.jpg】所示,从圆心做弦的垂线,可把6边形分割为12边形。

该12边形的边长a’的计算方法很容易利用勾股定理给出。
之后,再分割为正24边形,…如此循环会越来越接近圆周。
之所以从正六边开始,是因为此时边长与半径相等,便于计算。取半径值为1,开始割圆吧!
以下代码描述了割圆过程。
程序先输出了标准圆周率值,紧接着输出了不断分割过程中多边形边数和所对应的圆周率逼近值。
publicclassDemo10_B21
{
publicstaticvoid main(String[] args)
{
System.out.println(“标准 ” + Math.PI);
double a = 1;
int n = 6;
for(int i=0; i<10; i++)
{
double b = Math.sqrt(1-(a/2)(a/2));
a = Math.sqrt((1-b)
(1-b) + (a/2)*(a/2));

		n = n*2; //填空
		
		System.out.println(n + "  " + n*a/2 );  // 填空
	}
}

}
运行结果:
标准 3.141592653589793
12 3.105828541230249
24 3.1326286132812378
48 3.1393502030468667
96 3.14103195089051
192 3.1414524722854624
384 3.141557607911858
768 3.1415838921483186
1536 3.1415904632280505
3072 3.1415921059992717
6144 3.1415925166921577

38.奇怪的比赛(低碳生活大奖赛)

某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:
每位选手需要回答10个问题(其编号为1到10),越后面越有难度。
答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错误处理)。
每位选手都有一个起步的分数为10分。
某获胜选手最终得分刚好是100分,如果不让你看比赛过程,
你能推断出他(她)哪个题目答对了,哪个题目答错了吗?
如果把答对的记为1,答错的记为0,则10个题目的回答情况可以用仅含有1和0的串来表示。
例如:0010110011 就是可能的情况。
你的任务是算出所有可能情况。每个答案占一行。

package Question40_49;
publicclass Question41 {
publicstaticvoid exeForward(int question[],int index,int sum,int needSum) {
if(index<=10){
for (int i = 0; i <= 1; i++) {
question[index]=i;
int t=sum;
if(i0){
sum-=index;
}else {
sum*=2;
}
exeForward(question, index+1, sum, needSum);
question[index]=(i
1?0:1);
sum=t;
}
}else {
if(sum==needSum){
for (int i = 1; i <= 10; i++) {
System.out.print(question[i]);
}
System.out.println();
return;
}else {
return;
}
}

}
publicstaticvoid main(String[] args) {
	intneedSum=100;
	int question[]=newint[12];
	exeForward(question, 1, 10, 100);
}

}
运行结果:
0010110011
0111010000
1011010000
12345678910
0010110011
0111010000
1011010000

方法二:
/*
某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:
每位选手需要回答10个问题(其编号为1到10),越后面越有难度。
答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错误处理)。
每位选手都有一个起步的分数为10分。
某获胜选手最终得分刚好是100分,如果不让你看比赛过程,
你能推断出他(她)哪个题目答对了,哪个题目答错了吗?
如果把答对的记为1,答错的记为0,则10个题目的回答情况可以用仅含有1和0的串来表示。
例如:0010110011 就是可能的情况。
你的任务是算出所有可能情况。每个答案占一行。
/
public class Demo08_a {
// 判断是否符合条件
public static void show(int[] x){
int s = 10;
for(int i=0;i<x.length;i++){
if(x[i]==0){
s = s-(i+1); // 扣掉与题号相同的分数
}else{
s = s
2; // 当前分数翻倍
}
}
if(s==100){
for(int i:x){
System.out.print(i);
}
System.out.println();
}
}
// 递归遍历每种情况
public static void f(int[] x,int n){
if(n>=x.length){
show(x); // 判断
return;
}
x[n] = 0;
f(x,n+1);
x[n] = 1;
f(x,n+1);
}
public static void main(String[] args){
int[] x = new int[10];
f(x,0);
}
}

39.益智玩具(汉诺塔)

汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个,
金刚石和黄金都以木头代替了…但道理是相同的。
据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日!
你的任务是精确计算出到底需要移动多少次。
很明显,如果只有2个圆盘,需要移动3次。
圆盘数为3,则需要移动7次。
那么64个呢?
答案写在“解答.txt”中,不要写在这里!

package Question40_49;
import java.math.BigInteger;
import java.util.Scanner;
public class Question42MustRemember {
public static BigInteger count=BigInteger.valueOf(0);
public static void move(int from,int to) {
// System.out.println(from+“—>”+to);
count=count.add(BigInteger.valueOf(1));
}
public static void hanoi(int n,int from,int to,int assist) {
if(n>0){
hanoi(n-1, from, assist, to);
move(from, to);
hanoi(n-1, assist, to, from);
}

}
public static void main(String[] args) {
	Scanner scanner=new Scanner(System.in);
//	int n=scanner.nextInt();
	for (int i = 1; i <= 100; i++) {
		long startTime = System.currentTimeMillis();	// 程序开始时间
		hanoi(i, 1, 2, 3);
		long endTime = System.currentTimeMillis();	// 程序结束时间
		System.out.println("n="+String.format("%4d", i)+"  时,耗时"+String.format("%f", (endTime-startTime)/1000f)+"秒,  移动了"+count+" 次  ");
		count=BigInteger.valueOf(0);
		
	}
}

}

方法二:
import java.math.BigInteger;

/*

  • 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
    大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
    大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。
    并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
    如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个,
    金刚石和黄金都以木头代替了…但道理是相同的。
    据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日!
    你的任务是精确计算出到底需要移动多少次。
    很明显,如果只有2个圆盘,需要移动3次。
    圆盘数为3,则需要移动7次。
    那么64个呢?
    答案写在“解答.txt”中,不要写在这里!
    */

class Demo07_hanoi {
public static void hanoi(int n,char a,char b,char c){
if(n>0){
hanoi(n-1,a,c,b);
//System.out.println(a+“->”+b);
hanoi(n-1,c,b,a);
s++;
}
}
static long s = 0;
public static void main(String[] args){
int n = 10;
System.out.println(“圆盘个数\t移动次数”);
for(int i=1;i<=n;i++){
s = 0;
hanoi(i,‘a’,‘b’,‘c’);
System.out.println(i+” ->\t”+s);
}
System.out.println(“由上结果可找到规律为:\n移动次数 = 2的n次方-1(n为圆盘个数)”);
System.out.println(“64个圆盘的移动次数为:”);
BigInteger bi = new BigInteger(“2”);
bi = bi.pow(64).subtract(BigInteger.ONE);
System.out.println(bi);
}
}

运行结果:

圆盘个数 移动次数
1 -> 1
2 -> 3
3 -> 7
4 -> 15
5 -> 31
6 -> 63
7 -> 127
8 -> 255
9 -> 511
10 -> 1023
由上结果可找到规律为:
移动次数 = 2的n次方-1(n为圆盘个数)
64个圆盘的移动次数为:
18446744073709551615

40.拼酒量

有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,
所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,
再次重复… 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。
当第4瓶酒平分喝下后,大家都倒下了。等船长醒来,发现海盗船搁浅了。
他在航海日志中写到:“…昨天,我正好喝了一瓶…奉劝大家,开船不喝酒,喝酒别开船…”
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。
如果有多个可能的答案,请列出所有答案,每个答案占一行。
格式是:人数,人数,…
例如,有一种可能是:20,5,4,2,0
答案写在“解答.txt”中,不要写在这里!

package Question40_49;
publicclass Question43 {
publicstaticvoid main(String[] args) {
int person[]=newint[5];
for (person[1] = 1; person[1]<=20 ; person[1]++) {
for (person[2] = 1; person[2]<person[1] ; person[2]++){
for (person[3] = 1; person[3]<person[2] ; person[3]++){
for (person[4] = 1; person[4]<person[3] ; person[4]++){
if ((1.0)/person[1]+(1.0)/person[2]+(1.0)/person[3]+(1.0)/person[4]1) {
for (int i = 1; i <= 4; i++) {
System.out.print(person[i]);
if(i
4){
System.out.println(“,0”);
}else {
System.out.print(“,”);
}
}
}
}
}
}
}

}
  • 1

}
运行结果:
20,5,4,2,0
18,9,3,2,0
15,10,3,2,0
12,6,4,2,0

方法二:

/*
有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,
所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,
再次重复… 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。
当第4瓶酒平分喝下后,大家都倒下了。 等船长醒来,发现海盗船搁浅了。
他在航海日志中写到:“…昨天,我正好喝了一瓶…奉劝大家,开船不喝酒,喝酒别开船…”
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。
如果有多个可能的答案,请列出所有答案,每个答案占一行。
格式是:人数,人数,…
例如,有一种可能是:20,5,4,2,0
答案写在“解答.txt”中,不要写在这里!
*/
public class Demo06_alcohol {
public static void main(String[] args){
for(int i=20;i>0;i–){
for(int j=i-1;j>0;j–){
for(int k=j-1;k>0;k–){
for(int m=k-1;m>0;m–){ // 符点数比较,这里误差定为小于0.0000001为成立
if((Math.abs((1.0/i+1.0/j+1.0/k+1.0/m)-1))<0.0000001)
System.out.println(i+“,”+j+“,”+k+“,”+m+“,0”);
}
}
}
}
}
}
运行结果:
20,5,4,2,0
18,9,3,2,0
15,10,3,2,0
12,6,4,2,0

41.矩形运算

在编写图形界面软件的时候,经常会遇到处理两个矩形的关系。
如图【1.jpg】所示,矩形的交集指的是:两个矩形重叠区的矩形,当然也可能不存在(参看【2.jpg】)。

【1.jpg】

【2.jpg】
两个矩形的并集指的是:能包含这两个矩形的最小矩形,它一定是存在的。
本题目的要求就是:由用户输入两个矩形的坐标,程序输出它们的交集和并集矩形。
矩形坐标的输入格式是输入两个对角点坐标,注意,不保证是哪个对角,
也不保证顺序(你可以体会一下,在桌面上拖动鼠标拉矩形,4个方向都可以的)。
输入数据格式:
x1,y1,x2,y2
x1,y1,x2,y2
数据共两行,每行表示一个矩形。每行是两个点的坐标。x坐标在左,y坐标在右。
坐标系统是:屏幕左上角为(0,0),x坐标水平向右增大;y坐标垂直向下增大。
要求程序输出格式:
x1,y1,长度,高度
x1,y1,长度,高度
也是两行数据,分别表示交集和并集。如果交集不存在,则输出“不存在”
前边两项是左上角的坐标。后边是矩形的长度和高度。
例如,用户输入:
100,220,300,100
150,150,300,300
则程序输出:
150,150,150,70
100,100,200,200
例如,用户输入:
10,10,20,20
30,30,40,40
则程序输出:
不存在
10,10,30,30

import java.awt.Rectangle;
import java.util.Scanner;
publicclassDemo13_Rectang {
publicstatic Rectangle getRec(Rectangle[] rec){
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
String[] ss = s.split(“,”);
int x1 = Integer.parseInt(ss[0]);
int y1 = Integer.parseInt(ss[1]);
int x2 = Integer.parseInt(ss[2]);
int y2 = Integer.parseInt(ss[3]);
// 如果(x1,y1)(x2,y2)分别在(左上,右下,右上,左下)时
returnnew Rectangle(Math.min(x1, x2),Math.min(y1, y2),
Math.abs(x2-x1),Math.abs(y2-y1));
}
publicstaticvoid op(Rectangle[] rec){
Rectangle r,rr;
if(rec[0].intersects(rec[1])){
r = rec[0].intersection(rec[1]); // 交集
System.out.println(r.x+“,”+r.y+“,”+r.width+“,”+r.height);
}else{
System.out.println(“不存在”);
}
rr = rec[0].union(rec[1]); // 并集
System.out.println(rr.x+“,”+rr.y+“,”+rr.width+“,”+rr.height);
}
publicstaticvoid main(String[] args){
Rectangle rec[] = new Rectangle[2];
rec[0] = getRec(rec); // 第一个矩形
rec[1] = getRec(rec); // 第二个矩形
op(rec); // 输出交集和并集
}
}
运行结果1:
100,220,300,100
150,150,300,300
150,150,150,70
100,100,200,200
运行结果2:
10,10,20,20
30,30,40,40
不存在
10,10,30,30

42.警察智力训练

匪警请拨110,即使手机欠费也可拨通!
为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练!
某批警察叔叔正在进行智力训练:
1 2 3 4 5 6 7 8 9 = 110;
请看上边的算式,为了使等式成立,需要在数字间填入加号或者减号(可以不填,但不能填入其它符号)。之间没有填入符号的数字组合成一个数,
例如:12+34+56+7-8+9 就是一种合格的填法;123+4+5+67-89 是另一个可能的答案。
请你利用计算机的优势,帮助警察叔叔快速找到所有答案。
每个答案占一行。形如:12+34+56+7-8+9123+4+5+67-89…
已知的两个答案可以输出,但不计分。
各个答案的前后顺序不重要。
public class C2 {

public static void main(String[] args) {
	// TODO Auto-generated method stub
	//String string = "123+4+5+67-89";

	char a[] = {' ','+','-'};
	char num[] = {'1','2','3','4','5','6','7','8','9'};
	for(char x1:a)
		for(char x2:a)
			for(char x3:a)
				for(char x4:a)
					for(char x5:a)
						for(char x6:a)
							for(char x7:a)
								for(char x8:a)
	{
		int result = 0;
		char s[] = {x1,x2,x3,x4,x5,x6,x7,x8};
		String string = "";
		for(int i = 0;i<= 7;i++)
		{
			string = string+num[i]+s[i];
		}
		string = string+num[8];
		string= string.replaceAll(" ","");
		String jianString[] = string.split("-");
		int addResult[] = new int[jianString.length];
									
		addResult[0] = 0;
		String addString[] = jianString[0].split("[+]");
		for(int j = 0;j<addString.length;j++)
		{

addResult[0] += Integer.parseInt(String.valueOf(addString[j]));
}
result = addResult[0];
for(int i = 1;i<jianString.length;i++)
{
String num1[] = jianString[i].split(“[+]”);
result = result – Integer.parseInt(String.valueOf(num1[0]));
for(int p = 1;p<num1.length;p++)
result += Integer.parseInt(String.valueOf(num1[p]));
}
if(result == 110)
System.out.println(string)
}
}
}

其他解法:
/*
匪警请拨110,即使手机欠费也可拨通!
为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,
因而需要经常性地进行体力训练和智力训练!
某批警察叔叔正在进行智力训练:
1 2 3 4 5 6 7 8 9 = 110;
请看上边的算式,为了使等式成立,需要在数字间填入加号或者减号(可以不填,但不能填入其它符号)。
之间没有填入符号的数字组合成一个数,
例如:12+34+56+7-8+9 就是一种合格的填法;123+4+5+67-89 是另一个可能的答案。
请你利用计算机的优势,帮助警察叔叔快速找到所有答案。
每个答案占一行。形如:
12+34+56+7-8+9
123+4+5+67-89

已知的两个答案可以输出,但不计分。
各个答案的前后顺序不重要。
注意:
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。
请不要使用package语句。
源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
*/
public class Demo14 {
// 遍历所有情况
public static void fun(String s) {
char[] c = s.toCharArray();
StringBuffer sb = new StringBuffer(); // 记录 组成的式子
int len = s.length()-1; // 字符串长度 – 1
int[] sign = new int[len]; // sign用来标记符号, 最多有(s的长度-1)个符号
// 从后身前添加符号
while(sign[0]❤️){ // 最前面的判定符号的值若 >=3 则结束循环
sb.append(c[0]); // 添加首元素
for(int i=0;i<len;i++){
if(sign[i]==1){ // 值为1添加”+“号
sb.append(”+“);
}else if(sign[i]==2){// 值为2添加”-“号
sb.append(”-“);
}
sb.append(c[i+1]); // 不管添加不添加±号,都添加后一个元素
}

		check(sb.toString());	// 验证并输出
		
		sb.setLength(0);	// 清空sb
		sign[len-1]++;	// 每循环一次,最后一个符号值加1
		for(int i=len-1;i>0;i--){	//当值等于3时,实现逢3进位
			if(sign[i]==3){
				sign[i] = 0;	// sign[i] 归零
				sign[i-1]++;	// sign[i-1]进位
			}
		}
	}
}
// 验证并输出
public static void check(String str){
	String[] s = str.split("[\\+]|[-]");	// 得到全部数字
	String sign = str.replaceAll("\\d*", "");	// 得到全部符号(+-)
	int sum = Integer.parseInt(s[0]);	// 把第一个数字给sum
	for(int i=0;i<s.length-1;i++){
		switch(sign.charAt(i)){
			case '+': 
				sum += Integer.parseInt(s[i+1]);
				break;
			case '-': 
				sum -= Integer.parseInt(s[i+1]);
				break;
		}
	}
	if(sum==110){	// 符合条件输出
		System.out.println(str);
	}
}
// 主函数
public static void main(String[] args){
	String s = "123456789";
	fun(s);
}

}

运行结果:
123+4+5+67-89
123+4-5-6-7-8+9
123-4+5-6-7+8-9
123-4-5+6+7-8-9
12+34+56+7-8+9
12+3+45+67-8-9
12-3+4-5+6+7+89
1+234-56-78+9
1+2+34+5+67-8+9
1-2+3+45-6+78-9

123+4+5+67-89
123+4-5-6-7-8+9
123-4+5-6-7+8-9
123-4-5+6+7-8-9
12+34+56+7-8+9
12+3+45+67-8-9
12-3+4-5+6+7+89
1+234-56-78+9
1+2+34+5+67-8+9
1-2+3+45-6+78-9

方法二:
递归算法:

public class Demo15 {
// 遍历所有情况
public static void fun(String v, int n) {
if(n==9){ // 修改到最后一位符号时输出
check(v);
}else{ // 递归向后修改,数字 变为 数字加符号
fun(v.replace(n+“”, n+“+”),n+1);
fun(v.replace(n+“”, n+“-”),n+1);
fun(v,n+1);
}
}
// 验证 并 输出
public static void check(String str){
String[] s = str.split(“[\+]”);
int sum = 0;
for(String t:s){
String[] sub = t.split(“[\-]”);
int num = Integer.parseInt(sub[0]);
// 计算负数
for(int i=1;i<sub.length;i++){
num -= Integer.parseInt(sub[i]);
}
sum += num; // 正数或负数结果 加到 总和上
}
if(sum == 110){
System.out.println(str);
}
}
public static void main(String[] args){
String str = “123456789”;
fun(str,1); // 调用函数,从1开始修改
}
}

运行结果:
1+2+34+5+67-8+9
1+234-56-78+9
1-2+3+45-6+78-9
12+3+45+67-8-9
12+34+56+7-8+9
12-3+4-5+6+7+89
123+4+5+67-89
123+4-5-6-7-8+9
123-4+5-6-7+8-9
123-4-5+6+7-8-9

43.泊松分酒

泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。
有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。
有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。
在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。
有3个容器,容量分别为12升,8升,5升。其中12升中装满油,另外两个空着。
要求你只用3个容器操作,最后使得某个容器中正好有6升油。
下面的列表是可能的操作状态记录:
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5
每行3个数据,分别表示12,8,6升容器中的油量
第一行表示初始状态,第二行表示把12升倒入8升容器后的状态,第三行是8升倒入5升,…
当然,同一个题目可能有多种不同的正确操作步骤。
本题目的要求是,请你编写程序,由用户输入:各个容器的容量,开始的状态,
和要求的目标油量,程序则通过计算输出一种实现的步骤(不需要找到所有可能的方法)。
如果没有可能实现,则输出:“不可能”。
例如,用户输入:
12,8,5,12,0,0,6
用户输入的前三个数是容器容量(由大到小),接下来三个数是三个容器开始时的油量配置,
最后一个数是要求得到的油量(放在哪个容器里得到都可以)
则程序可以输出(答案不唯一,只验证操作可行性):
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5
每一行表示一个操作过程中的油量状态。
注意:
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。
请不要使用package语句。
源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。

package Question30_39;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.Vector;
public class Question36TooDifficultMustRemember {
public static List distribute(List capacityList,List oilSizeList,int where,int to) {
ListtList =new ArrayList();
tList.addAll(oilSizeList);
if(oilSizeList.get(where)==0){
return null;
}else if (oilSizeList.get(where)>=capacityList.get(to)-oilSizeList.get(to)) {
tList.set(to, capacityList.get(to));
tList.set(where, oilSizeList.get(where)-(capacityList.get(to)-oilSizeList.get(to)));
return tList;
}else if(oilSizeList.get(where)<=capacityList.get(to)-oilSizeList.get(to)){
tList.set(to, oilSizeList.get(to)+oilSizeList.get(where));
tList.set(where, 0);
return tList;
}
return null;
}
public static boolean exeForward(Set<List>set,List capacityList,List oilSizeList,int NeedOilSize) {

// for (List list : set) {
// System.out.print(list+” “);
// }
// System.out.println();

	for (Integer integer : oilSizeList) {
		if(integer==NeedOilSize){
			for (List<Integer> list : set) {
			//	System.out.print(list+" ");
			//	System.out.print(list.size()+" ");
				for (Iterator iterator = list.iterator(); iterator
						.hasNext();) {
					Integer integer2 = (Integer) iterator.next();
					System.out.print(integer2);
					if(iterator.hasNext()){
						System.out.print(",");
					}else {
						System.out.print("\n");
					}
					
				}
			}
			
			return true;
		}
	}
	Vector<List<Integer>>vector=new Vector<List<Integer>>();
	vector.add(distribute(capacityList, oilSizeList, 0, 1));
	vector.add(distribute(capacityList, oilSizeList, 0, 2));
	vector.add(distribute(capacityList, oilSizeList, 1, 0));
	vector.add(distribute(capacityList, oilSizeList, 1, 2));
	vector.add(distribute(capacityList, oilSizeList, 2, 0));
	vector.add(distribute(capacityList, oilSizeList, 2, 1));
	for (int i = 0; i < vector.size(); i++) {
		if(vector.get(i)!=null){
			
			if(set.add(vector.get(i))){
				
				if(exeForward(set, capacityList, vector.get(i), NeedOilSize)==true){
					return true;
				}
				set.remove(vector.get(i));
			}
		}
	}
	return false;
}
public static void main(String[] args){
	Scanner scanner=new Scanner(System.in);
	Set<List<Integer>>set=new LinkedHashSet<List<Integer>>();
	List<Integer>tList=new ArrayList<Integer>();
	for (int i = 0; i < 3; i++) {
		tList.add(0);
	}
	List<Integer> capacityList=new ArrayList<>(tList);
	List<Integer> oilSizeList=new ArrayList<>(tList);
	int NeedOilSize;
	
	String ts=scanner.nextLine();
	
	String tss[]=ts.split("\\,");
	for (int i = 0; i < capacityList.size(); i++) {
		capacityList.set(i, Integer.parseInt(tss[i]));
	}
	int totalOil=0;
	for (int i = 0; i < capacityList.size(); i++) {
		oilSizeList.set(i, Integer.parseInt(tss[i+3]));
		totalOil+=Integer.parseInt(tss[i+3]);
	}
	NeedOilSize=Integer.parseInt(tss[6]);
	
	if(NeedOilSize>totalOil){
		System.out.println("不可能");
		return;
	}
	boolean posible=false;
	for (int i = 0; i < capacityList.size(); i++) {
		if(capacityList.get(i)>NeedOilSize){
			posible=true;
			break;
		}
	}
	if(posible==false){
		System.out.println("不可能");
		return;
	}
	exeForward(set, capacityList, oilSizeList, NeedOilSize);
}

}
运行结果:
输入数据(格式为7个数字用”,”号隔开,例:)12,8,5,12,0,0,6
12,8,5,12,0,0,6
12 0 0
4 8 0
4 3 5
9 3 0
9 0 3
1 8 3
1 6 5
记录数:(7)

方法二:
import java.util.Scanner;
public class C33 {
public static void main(String[] args){
int num[] = getNum();
int d = gcd(num[1], num[2]);//中瓶和小瓶容量的最大公约数
if(num[0]/2 <= num[1] + num[2] && (num[0]/2)%d == 0)
{
System.out.println(num[3] + ” ” + num[4] + ” ” + num[5]);
fenjiu(num[3], num[4], num[5],num);
}
else
{
System.out.println(“不可能”);
}
}
static int[] getNum()
{
Scanner readerScanner = new Scanner(System.in);
String string[] = readerScanner.nextLine().split(“,”);
int i = 0;
int num[] = new int[7];
while(i < 7)
{
num[i] = Integer.parseInt(string[i]);
i++;
}
return num;
}
static void fenjiu(int num1,int num2,int num3,int num[])
{
//C2X – C3Y = 1
int b1 = num[1],c1 = num[2];
int a = num1,b = num2,c = num3,result = num[6];
if(b == result||c == result||a == result)
System.out.print(“”);
else {
//12,8,5,12,0,0,6
// 1. 大瓶子只能倒入中瓶子
// 2. 中瓶子只能倒入小瓶子
// 3. 小瓶子只能倒入大瓶子
// 4. 小瓶子只有在已经装满的情况下才能倒入大瓶
// 5. 若小瓶子被倒空,则无论中瓶子是否满,应马上从中瓶子倒入小瓶子
if(c == c1)
{// 4. 小瓶子只有在已经装满的情况下才能倒入大瓶子
a = a + c;
c = 0;
System.out.println(a + ” ” + b + ” ” + c);
fenjiu(a, b, c, num);
}
else {
if(c == 0 && b > 0)
{// 5. 若小瓶子被倒空,则无论中瓶子是否满,应马上从中瓶子倒入小瓶子
if(b > c1)
{
c = c1;
b = b – c1;
System.out.println(a + ” ” + b + ” ” + c);
fenjiu(a, b, c, num);
}
else {
c = b;
b = 0;
System.out.println(a + ” ” + b + ” ” + c);
fenjiu(a, b, c, num);
}
}
else {
if(b != b1)
{
a = a – b1 + b;
b = b1;
System.out.println(a + ” ” + b + ” ” + c);
fenjiu(a, b, c, num);
}
else {
b = b – c1 + c;
c = c1;
System.out.println(a + ” ” + b + ” ” + c);
fenjiu(a, b, c, num);
}
}
}
}
}
public static int gcd(int m, int n)
{
int a = n, b = m;
while (true)
{
if ((a = a % b) == 0)
return b;
if ((b = b % a) == 0)
return a;
}

}

}

方法三:
/*
泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。
有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。
有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。
在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。
有3个容器,容量分别为12升,8升,5升。其中12升中装满油,另外两个空着。
要求你只用3个容器操作,最后使得某个容器中正好有6升油。
下面的列表是可能的操作状态记录:
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5
每行3个数据,分别表示12,8,6升容器中的油量
第一行表示初始状态,第二行表示把12升倒入8升容器后的状态,第三行是8升倒入5升,…
当然,同一个题目可能有多种不同的正确操作步骤。
本题目的要求是,请你编写程序,由用户输入:各个容器的容量,开始的状态,
和要求的目标油量,程序则通过计算输出一种实现的步骤(不需要找到所有可能的方法)。
如果没有可能实现,则输出:“不可能”。
例如,用户输入:
12,8,5,12,0,0,6
用户输入的前三个数是容器容量(由大到小),接下来三个数是三个容器开始时的油量配置,
最后一个数是要求得到的油量(放在哪个容器里得到都可以)
则程序可以输出(答案不唯一,只验证操作可行性):
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5
每一行表示一个操作过程中的油量状态。
注意:
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。
请不要使用package语句。
源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
*/
import java.util.Scanner;
public class Demo16 {
// 有6种倒酒方法,x[0]->y[0]即(“0”->“1”)代表第一个瓶子向第二个瓶子倒酒,后即同理
static int[] x = {0,1, 2}; // 0 为第一个瓶子,1为第二个瓶子 ,2为第三个瓶子
static int[] y = {1,2, 0};
static int[][] rr = new int[1000][3]; // 记录倒酒后每一行结果
static int index = 0;
static int count = 0;
static int[] tt= {0,0,0};
// 输入数据
public static int[] input(){
Scanner scan = new Scanner(System.in);
String [] s = scan.nextLine().split(“,”);
int[] temp = new int[s.length];
for(int i=0;i<s.length;i++){ // 字符转为数字
temp[i] = Integer.parseInt(s[i]);
}
return temp;
}
// 输出
public static void print(int[][] rr){
for(int i=0;i<index;i++){
for(int j:rr[i])
System.out.print(j+“\t”);
System.out.println();
}
System.out.println(“记录数:(”+index+“)”);
}
// 记录步骤
public static void record(int[] cur){
rr[index][0] = cur[0];
rr[index][1] = cur[1];
rr[index][2] = cur[2];
index++;
}
// 判断当前的记录 是否 在以前的记录里 存在
public static boolean curExist(int[] cur){
for(int i=0;i<index;i++){
if(rr[i][0]==cur[0] && rr[i][1]==cur[1]
&& rr[i][2]==cur[2]){
return true;
}
}
return false;
}
// 倒酒
public static void pour(int[] v,int[] cur,int i){
count++; // 统计倒酒的次数, 若倒酒次数超过1000次,则识为”不可能”
int r = v[y[i]] – cur[y[i]]; // 计算 y瓶中还可以装入多少酒,拿y瓶的总容量-y瓶当前的酒
if(cur[x[i]] > r){ // x > y 时
cur[y[i]] = v[y[i]]; // y = 满
cur[x[i]] -= r; // x = x – r
}else{ // x <= y
cur[y[i]] += cur[x[i]]; // y = y + x
cur[x[i]] = 0; // x = x – r
}
}
// 求解
public static void f(int[] v,int[] cur,int m){
if(m>v[0]){
System.out.println(“要求得到的油量”+m+“大于最大容器”+v[0]+“,所以\n不可能”);
return;
}
boolean flag = true;
record(cur);
while(flag){
if(count>1000){
System.out.println(“倒酒次数超过1000次,所以\n不可能”);
return;
}
for(int i=0; i<3; i++){ // 6种倒酒方法
// 找到解,退出
if(cur[0]==m || cur[1]==m || cur[2]==m){
print(rr); // 找到解,输出记录
flag = false;
break;
}
// 如果 x 瓶中为空,则跳过, 执行下一轮倒酒
if(cur[x[i]] == 0){
continue;
}
pour(v,cur,i);// 倒酒
// 记录步骤
if(curExist(cur)){
cur[0] = rr[index-1][0]; // 还原为上次倒酒的值
cur[1] = rr[index-1][1];
cur[2] = rr[index-1][2];
//–index;
continue;
}else{
record(cur);
}

        }  
    }  
}  
// 主函数   
public static void main(String[] args){  
    System.out.println("输入数据(格式为7个数字用\",\"号隔开,例:)12,8,5,12,0,0,6");  
    int[] t = input();      // 输入数据   
    int[] v =  {t[0],t[1],t[2]};    // 每个容器的最大容量 v   
    int[] cur = {t[3],t[4],t[5]};   // 容器的开始的状态 init   
    int m = t[6];       // 要求得到的油量  r   
    f(v,cur,m);  
}

}

输入数据(格式为7个数字用”,”号隔开,例:)12,8,5,12,0,0,6
12,8,5,12,0,0,6
12 0 0
4 8 0
4 3 5
9 3 0
9 0 3
1 8 3
1 6 5
记录数:(7)

44.黄金分割数

黄金分割数0.618与美学有重要的关系。舞台上报幕员所站的位置大约就是舞台宽度的0.618处,
墙上的画像一般也挂在房间高度的0.618处,甚至股票的波动据说也能找到0.618的影子…
黄金分割数是个无理数,也就是无法表示为两个整数的比值。
0.618只是它的近似值,其真值可以通过对5开方减去1再除以2来获得,
我们取它的一个较精确的近似值:0.618034
有趣的是,一些简单的数列中也会包含这个无理数,这很令数学家震惊!
1 3 4 7 11 18 29 47 … 称为“鲁卡斯队列”。它后面的每一个项都是前边两项的和。
如果观察前后两项的比值,即:1/3,3/4,4/7,7/11,11/18 … 会发现它越来越接近于黄金分割数!
你的任务就是计算出从哪一项开始,这个比值四舍五入后已经达到了与0.618034一致的精度。
请写出该比值。格式是:分子/分母。比如:29/47

package Question40_49;
import java.math.BigDecimal;
publicclass Question44 {
publicstaticvoid main(String[] args) {
int a=1,b=3,t;
while(true){
if(Math.abs((double)a/b-0.618034)<0.000001){
System.out.println(a+“/”+b+” = “+(double)a/b);
break;
}
t=a;
a=b;
b+=t;
}
}
}
运行结果:
1364/2207

方法二:
import java.math.BigDecimal;
/*

  • 黄金分割数0.618与美学有重要的关系。舞台上报幕员所站的位置大约就是舞台宽度的0.618处,
    墙上的画像一般也挂在房间高度的0.618处,甚至股票的波动据说也能找到0.618的影子…
    黄金分割数是个无理数,也就是无法表示为两个整数的比值。
    0.618只是它的近似值,其真值可以通过对5开方减去1再除以2来获得,
    我们取它的一个较精确的近似值:0.618034
    有趣的是,一些简单的数列中也会包含这个无理数,这很令数学家震惊!
    1 3 4 7 11 18 29 47 … 称为“鲁卡斯队列”。它后面的每一个项都是前边两项的和。
    如果观察前后两项的比值,即:1/3,3/4,4/7,7/11,11/18 … 会发现它越来越接近于黄金分割数!
    你的任务就是计算出从哪一项开始,这个比值四舍五入后已经达到了与0.618034一致的精度。
    请写出该比值。格式是:分子/分母。比如:29/47
    */
    public class Demo05_Fibonacci {
    public static double format(double d){
    BigDecimal bd = new BigDecimal(d).setScale(6,BigDecimal.ROUND_HALF_UP);
    double dd = bd.doubleValue();
    return dd;
    }
    public static void f(int a,int b){
    double d = format((double)a/b);
    if(d==0.618034){
    System.out.println(a+“/”+b+“=”+d);
    return;
    }
    f(b,a+b);
    }
    public static void main(String[] args){
    f(1,3);
    }
    }

运行结果:
1364/2207=0.618034

45.平面4点最小距离

已知平面上若干个点的坐标。
需要求出在所有的组合中,4个点间平均距离的最小值(四舍五入,保留2位小数)。
比如有4个点:a,b,c,d,则平均距离是指:ab, ac, ad, bc, bd, cd 这6个距离的平均值。
每个点的坐标表示为:横坐标,纵坐标
坐标的取值范围是:1~1000
所有点的坐标记录在in.txt中,请读入该文件,然后计算。
注意:我们测试您的程序的时候,in.txt 可能会很大,比如包含上万条记录。
举例:
如果,in.txt 内的值为:
10,10
20,20
80,50
10,20
20,10
则程序应该输出:
11.38

package Question40_49;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;
public class Question45ErrorDontUnderstand {
public static double exeForward(Vectorvpoints,Vectortpoints,int index) {
// for (Point point : tpoints) {
// System.out.print(“[”+point.x+“,”+point.y+“]”);
// }
// System.out.println();
if(tpoints.size()==4){
double t=tpoints.get(0).distance(tpoints.get(1))+tpoints.get(0).distance(tpoints.get(2))+tpoints.get(0).distance(tpoints.get(3))
+tpoints.get(1).distance(tpoints.get(2))+tpoints.get(1).distance(tpoints.get(3))+tpoints.get(2).distance(tpoints.get(3));
t/=6;
//System.out.println(t);
return t;
}else if (index<vpoints.size()) {
Vectorvector1=new Vector(tpoints);
Vectorvector2=new Vector(tpoints);
vector2.add(vpoints.get(index));
double min1=exeForward(vpoints, vector1, index+1);
double min2=exeForward(vpoints, vector2, index+1);
return Math.min(min1, min2);
}
return Double.MAX_VALUE;
}
public static void main(String[] args) {
try {
File file=new File(“in.txt”);
FileInputStream fileInputStream=new FileInputStream(file);
InputStreamReader inputStreamReader=new InputStreamReader(fileInputStream);
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
Vectorvpoints=new Vector();
String ts;
while((ts=bufferedReader.readLine())!=null){
String tss[]=ts.split(“\,”);
Point point=new Point(Integer.parseInt(tss[0]), Integer.parseInt(tss[1]));
vpoints.add(point);
}
Vector tpoints=new Vector();
System.out.println(String.format(“%.2f”, exeForward(vpoints, tpoints, 0)));
bufferedReader.close();
} catch (FileNotFoundException e) {
// TODO: handle exception
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}运行结果:
11.38

方法二:
/*

  • 已知平面上若干个点的坐标。

    需要求出在所有的组合中,4个点间平均距离的最小值(四舍五入,保留2位小数)。
    比如有4个点:a,b,c,d,则平均距离是指:ab, ac, ad, bc, bd, cd 这6个距离的平均值。
    每个点的坐标表示为:横坐标,纵坐标
    坐标的取值范围是:1~1000
    所有点的坐标记录在in.txt中,请读入该文件,然后计算。
    注意:我们测试您的程序的时候,in.txt 可能会很大,比如包含上万条记录。
    举例:
    如果,in.txt 内的值为:
    10,10
    20,20
    80,50
    10,20
    20,10
    则程序应该输出:
    11.38
    */
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.util.List;
    import java.util.Vector;

// 代表一个点
class PP {
public int x;
public int y;

public String toString() {  
    return x + "," + y;  
}  

public PP(int x, int y) {  
    this.x = x;  
    this.y = y;  
}

}

class RR {
double x1;
double y1;
double x2;
double y2;

public RR() {  
}  

public RR(double x1, double y1, double x2, double y2) {  
    this.x1 = x1;  
    this.y1 = y1;  
    this.x2 = x2;  
    this.y2 = y2;  
}  

boolean isIn(PP p) {  
    return (x1 < p.x && p.x < x2 && y1 < p.y && p.y < y2);  
}

}

public class T07 {
public static double f(List lst, RR r) {
// lst:当前要处理的点,r:当前区域
if (lst.size() < 4)
return 10000; // 代表很远

    if (lst.size() < 13) {  
        // 测试中所有13中选4的组合   
        double min = 10000;  
        for (int i = 0; i < lst.size(); i++)  
            for (int j = i + 1; j < lst.size(); j++)  
                for (int k = j + 1; k < lst.size(); k++)  
                    for (int m = k + 1; m < lst.size(); m++) {  
                        double d = distance(lst.get(i), lst.get(j),  
                                lst.get(k), lst.get(m));  
                        if (d < min)  
                            min = d;  
                    }  
        return min;  
    }  

    // 缩小边界   
    double x1a = r.x2;  
    double x2a = r.x1;  
    double y1a = r.y2;  
    double y2a = r.y1;  
    for (int i = 0; i < lst.size(); i++) {  
        PP p = lst.get(i);  
        if (p.x < x1a)  
            x1a = p.x;  
        if (p.x > x2a)  
            x2a = p.x;  
        if (p.y < y1a)  
            y1a = p.y;  
        if (p.y > y2a)  
            y2a = p.y;  
    }  
    r.x1 = x1a;  
    r.x2 = x2a;  
    r.y1 = y1a;  
    r.y2 = y2a;  

    // 拆分lst 为4块,重叠4个区域   
    RR r1 = new RR();  
    RR r2 = new RR();  
    RR r3 = new RR();  
    RR r4 = new RR();  

    r1.x1 = r.x1;  
    r1.y1 = r.y1;  
    r1.x2 = r.x1 * 0.25 + r.x2 * 0.75; // 0.75*(x2-x1) + x1   
    r1.y2 = r.y1 * 0.25 + r.y2 * 0.75;  

    r2.x1 = r.x1 * 0.75 + r.x2 * 0.25; // 0.25*(x2-x1) + x1   
    r2.y1 = r.y1 * 0.75 + r.y2 * 0.25;  
    r2.x2 = r.x2;  
    r2.y2 = r.y2;  

    r3.x1 = r.x1;  
    r3.y1 = r.y1 * 0.75 + r.y2 * 0.25;  
    r3.x2 = r.x1 * 0.25 + r.x2 * 0.75;  
    r3.y2 = r.y2;  

    r4.x1 = r.x1 * 0.75 + r.x2 * 0.25;  
    r4.y1 = r.y1;  
    r4.x2 = r.x2;  
    r4.y2 = r.y1 * 0.25 + r.y2 * 0.75;  

    List<PP> t1 = new Vector<PP>();  
    List<PP> t2 = new Vector<PP>();  
    List<PP> t3 = new Vector<PP>();  
    List<PP> t4 = new Vector<PP>();  
    // isIn(p)判断是否在该矩形中   
    for (int i = 0; i < lst.size(); i++) {  
        PP p = lst.get(i);  
        if (r1.isIn(p))  
            t1.add(p);  
        if (r2.isIn(p))  
            t2.add(p);  
        if (r3.isIn(p))  
            t3.add(p);  
        if (r4.isIn(p))  
            t4.add(p);  
    }  
    // 递归   
    double d1 = f(t1, r1);  
    double d2 = f(t2, r2);  
    double d3 = f(t3, r3);  
    double d4 = f(t4, r4);  

    double d = d1;  
    if (d2 < d)  
        d = d2;  
    if (d3 < d)  
        d = d3;  
    if (d4 < d)  
        d = d4;  

    return d;  
}  
// 计算 4个点间平均距离   
public static double distance(PP a,PP b,PP c,PP d){  
    double dis =   
        (distance(a,b) + distance(a,c) + distance(a,d) +  
        distance(b,c) + distance(b,d) +   
        distance(c,d)) / 6.0;  
    return dis;  
}  
// 求两个点的距离   
public static double distance(PP a, PP b){  
    double dx = a.x - b.x;  
    double dy = a.y - b.y;  
    return Math.sqrt(dx*dx + dy*dy);  
}  
// 读入文件,填入List中   
public static List<PP> readPoints(String fname)throws Exception{  
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fname)));  
    List<PP> lst = new Vector<PP>();  
    for(;;){  
        String s = br.readLine();  
        if(s==null) break;  
          
        String[] ss = s.split(",");  
        PP a = new PP(0,0);  
        a.x = Integer.parseInt(ss[0]);  
        a.y = Integer.parseInt(ss[1]);  
        lst.add(a);  
    }  
    br.close();  
    return lst;  
}  
public static void main(String[] args) throws Exception {  
    List<PP> lst = readPoints("in.txt");  
    double x = f(lst, new RR(0, 0, 1000, 1000));  
    System.out.printf("%.2f",x);  
}

}

运行结果:
11.38

46.递归算法

递归算法:将数据分为两部分,递归将数据从左侧移右侧实现全排列
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;

publicclassT06 {
// 输出
publicstaticvoid print(List target){
for(Object o: target){
System.out.print(o);
}
System.out.println();
}
// 递归排列
publicstaticvoid sort(List datas,List target,int n){
if(target.size()==n){
print(target);
return;
}
for(int i=0;i<datas.size();i++){
List newDatas = new ArrayList(datas);
List newTarget = new ArrayList(target);
newTarget.add(newDatas.get(i));
newDatas.remove(i);

		sort(newDatas,newTarget,n);
	}
}
// 主函数
publicstaticvoid main(String[] args){
	String[] s = {"a","b","c"};
	sort(Arrays.asList(s),newArrayList(),s.length);
}

}
运行结果:
abc
acb
bac
bca
cab
cba

方法二:
publicclassAllSort{
publicstaticvoid perm(String[] buf,int start,int end){
if(startend){//当只要求对数组中一个字母进行全排列时,只要按该数组输出即可
for(int i=0;i<=end;i++){
System.out.print(buf[i]);
}
System.out.println();
}
else{//多个字母全排列
for(int i=start;i<=end;i++){
String temp=buf[start];//交换数组第一个元素与后续的元素
buf[start]=buf[i];
buf[i]=temp;
perm(buf,start+1,end);//后续元素递归全排列
temp=buf[start];//将交换后的数组还原
buf[start]=buf[i];
buf[i]=temp;
}
}
}
publicstaticvoid main(String[] args) {
String buf[]={“a”,“b”,“c”};
perm(buf,0,buf.length-1);
}
}
运行结果:
abc
acb
bac
bca
cba
cab
47.字符串全排列
字符串全排列
publicclassT03{
// 输出字符数组
publicstaticvoid print(char[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]);
}
System.out.println();
}
// 递归遍历
publicstaticvoid perm(char[] arr,int start,int end){
if(start
end){
print(arr); // 输出
}else{
for(int i=start;i<=end;i++){
// 换位
char c = arr[start];
arr[start] = arr[i];
arr[i] = c;
// 递归
perm(arr,start+1,end);
// 恢复数组原位
c = arr[start];
arr[start] = arr[i];
arr[i] = c;
}
}
}
// 字符串转字符数组
publicstaticvoid f(String s){
char[] arr = s.toCharArray();
perm(arr,0,arr.length-1);
}
publicstaticvoid main(String[] args){
String s = “abc”;
f(s);
}
}
运行结果:
abc
acb
bac
bca
cba
cab

48.亲密数

假设有a、b两个数,若a的所有因子之和等于b,b的所有因子之和等于a,
并且a不等于b,则称a和b是一对亲密数。如284和220就是一对亲密数。
分析:
若要找出10000以内的亲密数,可使用以下算法:
(1)对每一个数i,将其因子分解出来,并将因子保存到一个数组中,再将因子之和保存到变量b1。
(2)将因子之和b1再进行因子分解,并将因子保存到一个数组中,将因子之和保存到变量b2中。
(3)若b2等于i,并且b1不等于b2,则找到一对亲密数为i和b1,可将其输出。
(4)重复步骤(1)~(3),即可找出指定范围的亲密数。

package Question40_49;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.Vector;
public class Question48 {
public static int obtain(int n) {
int sum = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sum += i;
}
}
return sum;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
Set<Set> sets = new LinkedHashSet<Set>();
for (int i = 1; i <= n; i++) {
int t = obtain(i);
if (i != t) {
if (obtain(t) == i) {
Set set = new LinkedHashSet();
set.add(i);
set.add(t);
sets.add(set);
}
}
}
for (Iterator iterator = sets.iterator(); iterator.hasNext()???? {
Set set = (Set) iterator.next();
for (Iterator iterator2 = set.iterator(); iterator2.hasNext()???? {
Integer integer = (Integer) iterator2.next();
System.out.print(integer);
if (iterator2.hasNext() == false) {
System.out.println();
} else {
System.out.print(” “);
}
}
}
}
}
运行结果:
10000
220 284
1184 1210
2620 2924
5020 5564
6232 6368

49.世纪末的星期

曾有邪教称1999年12月31日是世界末日。当然该谣言已经不攻自破。
还有人称今后的某个世纪末的12月31日,如果是星期一则会…
有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!!
于是,“谣言制造商”又修改为星期日…
1999年的12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即xx99年)的12月31日正好是星期天(即星期日)?
请回答该年份(只写这个4位整数,不要写12月31等多余信息)

import java.util.Scanner;
public class Question1UnAmendment {
public static void main(String[] args) {
int day=0;
for (int year = 2000; ; year++) {
day+=new Question1UnAmendment().dayOfyear(year);
if(year%10099&&day%72){
System.out.println(year);
break;
}
}
}
private int dayOfyear(int year) {
if ((year%40&&year%100!=0)||year%4000) {
return 366;
}
else {
return 365;
}
}
}

50.马虎的算式

小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。
有一次,老师出的题目是:36 x 495 = ?
他却给抄成了:396 x 45 = ?
但结果却很戏剧性,他的答案竟然是对的!!
因为 36 * 495 = 396 * 45 = 17820
类似这样的巧合情况可能还有很多,比如:27 * 594 = 297 * 54
假设 a b c d e 代表1~9不同的5个数字(注意是各不相同的数字,且不含0)
能满足形如: ab * cde = adb * ce 这样的算式一共有多少种呢?
请你利用计算机的优势寻找所有的可能,并回答不同算式的种类数。
满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。
答案直接通过浏览器提交。
注意:只提交一个表示最终统计种类数的数字,不要提交解答过程或其它多余的内容。

import java.util.Scanner;
public class Question2UnAmendment {
public static void main(String[] args) {
int a, b, c, d, e;
int count=0;
for (a = 1; a < 10; a++) {
for (b = 1; b < 10; b++) {
if (b != a) {
for (c = 1; c < 10; c++) {
if (c != b && c != a) {
for (d = 1; d < 10; d++) {
if (d != a && d != b && d != c) {
for (e = 1; e < 10; e++) {
if (e != a && e != b && e != c
&& e != d) {
if ((a * 10 + b)
* (c * 100 + d * 10 + e) == (a
* 100 + d * 10 + b)
* (c * 10 + e)) {
System.out.printf(“%d%d*%d%d%d = %d%d%d*%d%d\n”,a, b, c, d, e,a, d, b, c, e);
count++;
}
}
}
}
}
}
}
}
}
}
System.out.println(count);
}
}

51.振兴中华

小明参加了学校的趣味运动会,其中的一个项目是:跳格子。
地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg)
从我做起振
我做起振兴
做起振兴中
起振兴中华
比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。
要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
答案是一个整数,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。

import java.util.Scanner;
public class Question3UnAmendment {
String indexsString[] = { “从”, “我”, “做”, “起”, “振”, “兴”, “中”, “华” };
String s[][] = {
{ “从”, “我”, “做”, “起”, “振” },
{ “我”, “做”, “起”, “振”, “兴” },
{ “做”, “起”, “振”, “兴”, “中” },
{ “起”, “振”, “兴”, “中”, “华” }
};
private int stepForward(int i, int j, int index) {
if (i < 4 && j < 5) {
if (s[i][j] == indexsString[index]) {
if (indexsString[index] == “华”) {
return 1;
} else {
return (new Question3UnAmendment()).stepForward(i + 1, j,
index + 1)
+ (new Question3UnAmendment()).stepForward(i,
j + 1, index + 1);
}
}
}
return 0;
}
public static void main(String[] args) {
System.out.println((new Question3UnAmendment()).stepForward(0, 0, 0));
}
}
52.有理数类
有理数就是可以表示为两个整数的比值的数字。一般情况下,我们用近似的小数表示。但有些时候,不允许出现误差,必须用两个整数来表示一个有理数。
这时,我们可以建立一个“有理数类”,下面的代码初步实现了这个目标。为了简明,它只提供了加法和乘法运算。

class Rational
{
private long ra;
private long rb;

private long gcd(long a, long b){
	if(b==0) return a;
	return gcd(b,a%b);
}
public Rational(long a, long b){
	ra = a;
	rb = b;	
	long k = gcd(ra,rb);
	if(k>1){ //需要约分
		ra /= k;  
		rb /= k;
	}
}
// 加法
public Rational add(Rational x){
	return new Rational(this.ra*x.rb+this.rb+x.ra, this.rb*x.rb);  //填空位置
}
// 乘法
public Rational mul(Rational x){
	return new Rational(ra*x.ra, rb*x.rb);
}
public String toString(){
	if(rb==1) return "" + ra;
	return ra + "/" + rb;
}

}
使用该类的示例:
Rational a = new Rational(1,3);
Rational b = new Rational(1,6);
Rational c = a.add(b);
System.out.println(a + “+” + b + “=” + c);
请分析代码逻辑,并推测划线处的代码,通过网页提交
注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!!
53.三部排序
一般的排序有许多经典算法,如快速排序、希尔排序等。
但实际应用时,经常会或多或少有一些特殊的要求。我们没必要套用那些经典算法,可以根据实际情况建立更好的解法。
比如,对一个整型数组中的数字进行分类排序:
使得负数都靠左端,正数都靠右端,0在中部。注意问题的特点是:负数区域和正数区域内并不要求有序。可以利用这个特点通过1次线性扫描就结束战斗!!
以下的程序实现了该目标。

static void sort(int[] x)
{
	int p = 0;
	int left = 0;
	int right = x.length-1;
	
	while(p<=right){
		if(x[p]<0){
			int t = x[left];
			x[left] = x[p];
			x[p] = t;
			left++;
			p++;
		}
		else if(x[p]>0){
			int t = x[right];
			x[right] = x[p];
			x[p] = t;
			right--;			
		}
		else{
			p++;  //代码填空位置
		}
	}
}

54.错误票据

某涉密单位下发了某种票据,并要在年终全部收回。
每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
要求程序首先输入一个整数N(N<100)表示后面数据行数。
接着读入N行数据。
每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000)
每个整数代表一个ID号。
要求程序输出1行,含两个整数m n,用空格分隔。
其中,m表示断号ID,n表示重号ID
例如:
用户输入:
2
5 6 8 11 9
10 12 9

则程序输出:
7 9
再例如:
用户输入:
6
164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196
172 189 127 107 112 192 103 131 133 169 158
128 102 110 148 139 157 140 195 197
185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190
149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188
113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119
则程序输出:
105 120
资源约定:
峰值内存消耗(含虚拟机)< 64M
CPU消耗< 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

import java.io.IOException;
import java.util.PriorityQueue;
import java.util.Scanner;
class Question7UnAmendment{
public static void main(String[] args) throws IOException {
String s[]=new String[10];
int lines;
char ch;
PriorityQueuepriorityQueue=new PriorityQueue();
lines= System.in.read()-‘0’;
lines++;
int sum=0;
while(lines>0){
ch=(char) System.in.read();
if(ch==’ ‘){
if(sum!=0){
priorityQueue.add(sum);
sum=0;
}
}else if(ch>=‘0’&&ch<=‘9’){
if(ch==‘0’&&sum0){
priorityQueue.add(0);
continue;
}
sum*=10;
sum+=ch-‘0’;
}else if(ch
’\n’){
lines–;
if(sum!=0){
priorityQueue.add(sum);
sum=0;
}
}
}
int m =-1,n = -1;
int i=priorityQueue.peek();
while(!priorityQueue.isEmpty()){
if(i!=priorityQueue.peek()){
if(priorityQueue.peek()-i==1){
m=i;
priorityQueue.add(i);
}else if (i-priorityQueue.peek()==1) {
n=priorityQueue.peek();
priorityQueue.poll();
}
}
i++;
priorityQueue.poll();
}
System.out.println(m+” “+n);
}
}

55.幸运数

幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。
首先从1开始写出自然数1,2,3,4,5,6,…
1 就是第一个幸运数。
我们从2这个数开始。把所有序号能被2整除的项删除,变为:
1 _ 3 _ 5 _ 7 _ 9 …
把它们缩紧,重新记序,为:
1 3 5 7 9 … 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, …
此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,…)
最后剩下的序列类似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, …
本题要求:
输入两个正整数m n, 用空格分开 (m < n < 1000*1000)
程序输出位于m和n之间的幸运数的个数(不包含m和n)。
例如:
用户输入:
1 20
程序输出:
5
例如:
用户输入:
30 69
程序输出:
8
资源约定:
峰值内存消耗(含虚拟机)< 64M
CPU消耗< 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

import java.util.Scanner;
import java.util.Vector;
class Question8UnAmendment{
public static void main(String[] args) {
Vector vector=new Vector();
int m,n;
Scanner scanner=new Scanner(System.in);
m=scanner.nextInt();
n=scanner.nextInt();
for(int i=0;i<=n;i++){
vector.add(i);
}
//除掉序号能被2整除的
for(int i=vector.size()-1;i>=1;i–){
if(i%2==0){
vector.remove(i);
}
}
int index=2;
while(index<vector.size()){
for (int i = vector.size()-1; i>=1; i–) {
if(i%vector.elementAt(index)==0){
vector.remove(i);
}
}
index++;
}
int count=0;
for(int i=vector.size()-1;i>=1;i–){
if(vector.elementAt(i)==n){
continue;
}
else if(vector.elementAt(i)>m){
count++;
}else {
break;
}
}
System.out.println(count);
}
}

56.连号区间数

小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式:
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N),表示这N个数字的某一全排列。
输出格式:
输出一个整数,表示不同连号区间的数目。
示例:
用户输入:
4
3 2 4 1
程序应输出:
7
用户输入:
5
3 4 2 5 1
程序应输出:
9
解释:
第一个用例中,有7个连号区间分别是:[1,1], [1,2], [1,3], [1,4], [2,2], [3,3], [4,4]
第二个用例中,有9个连号区间分别是:[1,1], [1,2], [1,3], [1,4], [1,5], [2,2], [3,3], [4,4], [5,5]
资源约定:
峰值内存消耗(含虚拟机)< 64M
CPU消耗< 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

import java.util.Scanner;
import java.util.Vector;
class Question10UnAmendment{
Vector vectorPrimary=new Vector();
private boolean isContinuous(int begin,int end) {
int max=vectorPrimary.elementAt(begin),min=vectorPrimary.elementAt(begin);
for(int i=begin;i<=end;i++){
if(max<vectorPrimary.elementAt(i)){
max=vectorPrimary.elementAt(i);
continue;
}
if(min>vectorPrimary.elementAt(i)){
min=vectorPrimary.elementAt(i);
}
}
if(max-min==end-begin){
return true;
}else {
return false;
}

}
public Vector<Integer> getVectorPrimary() {
	return vectorPrimary;
}

public void setVectorPrimary(Vector vectorPrimary) {
this.vectorPrimary = vectorPrimary;
}
public static void main(String[] args) {
int N,t,count=0;
Scanner scanner=new Scanner(System.in);
Question10UnAmendment question10UnAmendment=new Question10UnAmendment();
question10UnAmendment.getVectorPrimary().add(0);

	N=scanner.nextInt();
	for(int i=1;i<=N;i++){
		t=scanner.nextInt();
		question10UnAmendment.getVectorPrimary().add(t);
	}
	for(int i=1;i<question10UnAmendment.getVectorPrimary().size();i++){
		for (int j = i+1; j < question10UnAmendment.getVectorPrimary().size(); j++) {
			if(question10UnAmendment.isContinuous(i, j)){
				count++;
			}
		}
	}
	System.out.println(count+N);
}

}

57.黄金连分数

黄金分割数0.61803… 是个无理数,这个常数十分重要,在许多工程问题中会出现。有时需要把这个数字求得很精确。
对于某些精密工程,常数的精度很重要。也许你听说过哈勃太空望远镜,它首次升空后就发现了一处人工加工错误,对那样一个庞然大物,其实只是镜面加工时有比头发丝还细许多倍的一处错误而已,却使它成了“近视眼”!!
言归正传,我们如何求得黄金分割数的尽可能精确的值呢?有许多方法。
比较简单的一种是用连分数:
1
黄金数 = ———————
1
1 + —————–
1
1 + ————-
1
1 + ———
1 + …
这个连分数计算的“层数”越多,它的值越接近黄金分割数。
请你利用这一特性,求出黄金分割数的足够精确值,要求四舍五入到小数点后100位。
小数点后3位的值为:0.618
小数点后4位的值为:0.6180
小数点后5位的值为:0.61803
小数点后7位的值为:0.6180340
(注意尾部的0,不能忽略)
你的任务是:写出精确到小数点后100位精度的黄金分割值。
注意:尾数的四舍五入!尾数是0也要保留!
显然答案是一个小数,其小数点后有100位数字,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
import java.math.BigInteger;
public class test5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
BigInteger one = BigInteger.ONE;
BigInteger ten = BigInteger.TEN;
BigInteger a = one;
BigInteger b = one.add(one.add(one));
BigInteger c = b;
BigInteger sum = BigInteger.ONE;
for(int i=0;i<300;i++){//需要精确到100位,所以循环次数要适当
sum = a;
for(int j=0;j<101;j++){//需要把小数点向右移动101位
sum = ten.multiply(sum);
}
BigInteger res = sum.divide©;
c = a.add(b);
a = b;
b = c;
if(res.toString().length()==101){//要判断到101位,需要四舍五入
System.out.println(res);

		}
	}
}

}

58.带分数

100 可以表示为带分数的形式:100 = 3 + 69258 / 714

还可以表示为:100 = 82 + 3546 / 197
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
题目要求:
从标准输入读入一个正整数N (N<1000*1000)
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
例如:
用户输入:
100
程序输出:
11
再例如:
用户输入:
105
程序输出:
6
资源约定:
峰值内存消耗(含虚拟机)< 64M
CPU消耗< 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

import java.util.Scanner;
public class DaiFenShu
{
static int kinds=0;
static int a[]=new int[10];
static boolean vis[]=new boolean[10];//全排列避免重复
static void check(int a[],int n,int num)
{
int begin=String.valueOf(num).length();
String str=“”;
for(int i=1;i<n;i++) str+=a[i];
for(int k=1;k<begin+1;k++)
{
int num1=Integer.valueOf(str.substring(0,k));
if(num1<num)
{
for(int j=k+(n-k)/2;j<n-1;j++)
{
int num2=Integer.valueOf(str.substring(k,j));
int num3=Integer.valueOf(str.substring(j,n-1));
if(num2>num3 && num2%num30)
{
if(num
num1+num2/num3)
{
// System.out.println(num+” = “+num1+”+“+num2+”/”+num3);
kinds++;
}
}
}
}
}
}
static void dfs(int start,int n,int num)
{
if(start==n)
{
check(a,n,num);
}
else
{
for(int i=1;i<n;i++)
{
if(!vis[i])
{
a[start]=i;
vis[i]=true;
dfs(start+1,n,num);
vis[i]=false;
}
}
}
}
public static void main(String[] args)
{
Scanner cin=new Scanner(System.in);
int num=cin.nextInt();
long start=System.currentTimeMillis();
dfs(1,10,num);
long end=System.currentTimeMillis();
// System.out.println(end-start);//运行时间
System.out.println(kinds);
}
}

59.三进制转十进制

不同进制的数值间的转换是软件开发中很可能会遇到的常规问题。下面的代码演示了如何把键盘输入的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 = ______________________;
}
System.out.println(n);
3*n+c-‘0’

60.数组中的最大元素

有如下程序,完成的功能为:找出数组中的最大元素。请填写程序的中空白,使程序运行正确。
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(arraynull || array.length0)
{
return 0;
}
int max=array[0];
while(index<array.length-1)
{
max=____________________
}
if(max<array[index]) max= array[index];
return max;
}
}
max>array[++index]?max:array[index]

61.电视台开宝箱节目

电视台开宝箱节目:打进电话的人可以开启一个宝箱。箱子中有一件礼品。礼品是iphone的机率为1/12;是mp3 的机率为1/5;是洗衣粉的机率为1/2;剩余是KFC优惠券
每次打进电话,宝箱会重置。
以下程序模拟了该抽奖过程。请填写缺失的部分。
public static void main(String[] args)
{
int i = (int) (Math.random() * _____________);
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优惠券”);
}
}
60

62.连续的1或0出现的最大次数

下列代码求出一个二进制串中连续的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++;
________;
}
else
{
n_1++;
_________;
}
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);
}
n_1=0 n_0=0

63.十六进制转三进制

下列代码把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)); // 填空
}
String t = “”;
for(;????
{
if(n==0) break;
t = (n % 3) + t;
_____________; // 填空
}
return t;
}
16*n n/=3

64.随机3人中奖

在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 = ____________________________;
System.out.println(a.remove(d));
}
}
}
new Random().nextInt(6-k) //(int)(Math.random()*(6-k))

65.有趣的平方数

625这个数字很特别,625的平方等于390625,刚好其末3位是625本身。除了625,还有其它的3位数有这个特征吗?
请编写程序,寻找所有这样的3位数:它的平方的末3位是这个数字本身。
输出结果中,从小到大,每个找到的数字占一行。比如那个625就输出为:
625
publicstaticvoid main(String[] args) {
int temp = 0;
for(int i = 100; i <= 999; ++i){
temp = i*i;
temp %= 1000;
if(temp == i)System.out.println(i);
}
}

66.立方和等式

考虑方程式: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
不同解间的顺序可以不考虑。
publicstaticvoid main(String[] args) {
int []arr = newint[31];
for(int i = 1; i <= 30; ++i){
arr[i] = (int)iii;
}
for(int a = 1 ; a <= 27; ++a){
for(int b = a+1 ; b <= 28; ++b){
for(int c = b+1 ; c <= 29; ++c){
for(intd = c+1 ; d<= 30; ++d){
if((arr[a] + arr[d])(arr[b] + arr[c]))
System.out.println(a + “,” + b + “,” + c + “,” + d);
}
}
}
}
}
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class 立方和等式 {
// 输出
private static void print(List<int[]> lis) {
for(int i=0;i<lis.size();i++){
for(int j=0;j<lis.get(i).length-1;j++){
System.out.print(lis.get(i)[j]+“,”);
}
System.out.println(lis.get(i)[lis.get(i).length-1]);
}
}
public static boolean check(List<int[]> lis,int[] n){
if(lis.size()0){
return true;
}else{
int count = 0;
for(int i=0;i<lis.size();i++){
for(int j=0;j<n.length;j++){
if(lis.get(i)[j]!=n[j]){
count = 0;
break;
}else{
count++;
}
}
if(count
4) return false;
}
}
return true;
}
private static void f(List<int[]> lis) {
for(int i=0;i<30;i++){
for(int j=0;j<30;j++){
for(int k=0;k<30;k++){
for(int m=0;m<30;m++){
if(i
j||ik||im||
jk||jm||km) continue;
int a = (int)Math.pow(i, 3);
int b = (int)Math.pow(j, 3);
int c = (int)Math.pow(k, 3);
int d = (int)Math.pow(m, 3);
if(a+b
c+d){
int[] temp = new int[]{i,j,k,m};
Arrays.sort(temp); // 排序
if(check(lis,temp)){// 不重复,添加
lis.add(temp);
}
}
}
}
}
}
}
public static void main(String[] args){
List<int[]> lis = new ArrayList<int[]>();
f(lis); // 得到结果
print(lis); // 输出
}
}

运行结果:
1,9,10,12
2,9,15,16
2,18,20,24
10,19,24,27

方法二:(用全排列实现)(m排n)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
public class sortMN {
static List<int[]> lis = new ArrayList<int[]>();
// 输出
private static void print(List<int[]> lis) {
for(int i=0;i<lis.size();i++){
for(int j=0;j<lis.get(i).length-1;j++){
System.out.print(lis.get(i)[j]+“,”);
}
System.out.println(lis.get(i)[lis.get(i).length-1]);
}
}
public static boolean check(List<int[]> lis,int[] n){
if(lis.size()0){
return true;
}else{
int count = 0;
for(int i=0;i<lis.size();i++){
for(int j=0;j<n.length;j++){
if(lis.get(i)[j]!=n[j]){
count = 0;
break;
}else{
count++;
}
}
if(count
4) return false;
}
}
return true;
}
public static boolean check(int[] n){
Set sets = new HashSet();
for(int i=0;i<n.length;i++){
sets.add(n[i]);
}
if(sets.size()4){
return true;
}
return false;
}
public static void oper(int[] n){
int a = (int)Math.pow(n[0], 3);
int b = (int)Math.pow(n[1], 3);
int c = (int)Math.pow(n[2], 3);
int d = (int)Math.pow(n[3], 3);
if(a+b
c+d){
int[] temp = new int[]{n[0],n[1],n[2],n[3]};
Arrays.sort(temp); // 排序
if(check(lis,temp)){// 不重复,添加
lis.add(temp);
}
}
}
public static void f(int m,int[] n,int k) {
if(k==n.length){
if(check(n)){
oper(n);
}
return ;
}
for(int i=0;i<m;i++){
n[k] = i;
f(m, n,k+1);
}
}
public static void main(String[] args) {
int m = 30;
int n = 4;
f(m,new int[n],0);
print(lis);
}
}

运行结果:
1,9,10,12
2,9,15,16
2,18,20,24
10,19,24,27

67.整数的分划问题

如,对于正整数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)
程序输出该整数的所有划分。
publicclass Test {
privatestatic LinkedListstr=new LinkedList();
publicstaticvoid main(String[] args){
int input = 10;
Test.integerDivide(input, input);
}
publicstaticvoid integerDivide(int limit, int max){
if(1 == max) {
str.add(String.valueOf(1));
formatResult(str);
str.removeLast();
return;
}
if(0 == max) {
formatResult(str);
return;
}
for(int i = limit ; i >= 1; –i){
if(i <= max){
str.add(String.valueOf(i));
integerDivide(i, max-i);
str.removeLast();
}
}
}
publicstaticvoid formatResult(LinkedList s){
System.out.print(s.getFirst());
for(int i=1;i<s.size();i++)
System.out.print(“+”+s.get(i));
System.out.println();
}
}

68.显示为树形

树形结构应用十分广泛。
下面这段代码根据用户添加的数据,在内存中构建一个逻辑上等价的树形结构。
通过ShowTree() 可以把它显示为控制中的样子。
其中:
a.add(‘a’, ‘b’);
a.add(‘b’, ‘e’);
表示:‘b’ 作为 ‘a’ 的孩子节点;‘e’ 作为 ‘b’的孩子节点。
如代码中给出的示例数据,输出结果应该为:

a–b–e
| |–f–j
| |–k
|–c
|–d–g–h
|–i
请阅读下面的代码,填写缺失的部分(下划线部分)。
注意:请把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
直接写在题面中不能得分。
import java.util.*;
class MyTree
{
private Map map = new HashMap();

public void add(char parent, char child)
{
	List<Character> t = (List<Character>)map.get(parent);
	if(t==null)
	{
		t = new Vector<Character>();
		 map.put(parent, t) ;  // 填空1
	}
	t.add(child);
}
public List<Character> getChild(char x)
{
	return (List<Character>)map.get(x);
}

}
public class My
{
public static List showTree(MyTree tree, char x)
{
List t = tree.getChild(x);
List r = new Vector();
if(tnull)
{
r.add(“” + x);
return r;
}
for(int i=0; i<t.size(); i++)
{
List ri = showTree(tree, t.get(i));
for(int j=0; j<ri.size(); j++)
{
String pre = “| “;
if(j
0)
{
if(i0)
pre = x + “–”;
else
pre = “|–”;
}
else
{
if(i
t.size()-1 ) // 填空2
pre = ” “;
else
pre = “| “;
}
r.add(pre + ri.get(j));
}
}
return r;
}
public static void main(String[] args)
{
MyTree a = new MyTree();
a.add(‘a’, ‘b’);
a.add(‘b’, ‘e’);
a.add(‘b’, ‘f’);
a.add(‘a’, ‘c’);
a.add(‘a’, ‘d’);
a.add(‘d’, ‘g’);
a.add(‘d’, ‘i’);
a.add(‘g’, ‘h’);
a.add(‘f’, ‘j’);
a.add(‘f’, ‘k’);

	List<String> lst = showTree(a, 'a');
	for(int i=0; i<lst.size(); i++)
	{
		System.out.println(lst.get(i));
	}
}

}

69.连续数的公倍数

为什么1小时有60分钟,而不是100分钟呢?这是历史上的习惯导致。
但也并非纯粹的偶然:60是个优秀的数字,它的因子比较多。
事实上,它是1至6的每个数字的倍数。即1,2,3,4,5,6都是可以除尽60。
我们希望寻找到能除尽1至n的的每个数字的最小整数。
不要小看这个数字,它可能十分大,比如n=100, 则该数为:
69720375229712477164533808935312303556800
为此,有必要使用BigInteger来记录这样的大数。
请阅读下面的代码,填写缺失的部分(下划线部分)。
注意:请把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
直接写在题面中不能得分。

import java.math.BigInteger;
public class My1
{
// 求能除尽1~n 每个数字的最小整数
public static BigInteger f(int n)
{
int[] x = new int[n+1];
for(int i=1; i<=n; i++) x[i] = i;
for(int i=2; i<n; i++)
{
for(int j=i+1; j<=n; j++)
{
if(x[j] % x[i]==0) x[j]/=x[i] ; // 填空1
}
}
BigInteger m = BigInteger.ONE;
for(int i=2; i<=n; i++)
{
m = m.multiply( BigInteger.valueOf(x[i] )); // 填空2
}
return m;
}
public static void main(String[] args)
{
System.out.println(f(30));
}
}
方法二:
import java.math.BigInteger;
import java.util.Scanner;
public class 连续数的公倍数 {
// 得到最大公约数(辗转相除)
public static BigInteger gdc(BigInteger m,BigInteger n) {
BigInteger r = m.mod(n);
while(r.compareTo(BigInteger.ZERO)!=0){
m = n;
n = r;
r = m.mod(n);
}
return n;
}
public static BigInteger f(BigInteger m,BigInteger n){
if(n.compareTo(BigInteger.ONE)==0){
return m; // n到最后
}else{
m = m.multiply(n).divide(gdc(m, n)); // 得到最小公倍数
return f(m,n.subtract(BigInteger.ONE));
}
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入的 n (n<100)”);
BigInteger m = scan.nextBigInteger();
System.out.println(f(m,m.subtract(BigInteger.ONE)));
}
}

70.汉字相乘

(编程题)下列乘法算式中:每个汉字代表 1 个数字(1~9)。相同的汉字代表相同的
数字,不同的汉字代表不同的数字。
赛软件 * 比赛 = 软件比拼
试编程确定使得整个算式成立的数字组合,如有多种情况,请给出所有可能的答案。
【参考结果】
465 * 14 = 6510

public class Competition {
public void getResult() {
int s, r, j, b, p;
for (s = 2; s <= 9; s++) {
for (r = 0; r <= 9; r++) {
if(rs)continue;
for (j = 2; j <= 9; j++) {
if(j
r||js)continue;
for (b = 0; b <= 9; b++) {
if(b
s||br||bj)continue;
for (p = 0; p <= 9; p++) {
if(pb||pj||pr||ps)continue;
int left = (s * 100 + r * 10 + j) * (b * 10 + s);
int right = r * 1000 + j * 100 + b * 10 + p;
if (left == right) {
System.out.println(“” + s + r + j +” * “+b+s+” = “+r+j+ b + p);
}
}
}
}
}
}
}
public static void main(String[] args) {
Competition s = new Competition();
// s.biJiao();
s.getResult();
}
}

71.角谷步数

你听说过角谷猜想吗?
任意的正整数,比如 5, 我们从它开始,如下规则计算:
如果是偶数,则除以2,如果是奇数,则乘以3再加1.
如此循环,最终必会得到“1” !
比如 5 的处理过程是:
5
16
8
4
2
1
一个正整数经过多少步才能变成1, 称为角谷步数。
对于5而言,步数也是5
对于1,步数为0
本题的要求是,从标准输入给定一个整数n(1<n<300)表示角谷步数
求满足这个角谷步数的最小的正整数
例如:
输入:
3
则输出:
8

输入:
4
则输出:
16

输入:
7
则输出:
3

import java.util.Scanner;
public class JGStepNumber {
static int sum = 0;
public static void f(int n){
if(n<=1){
return ;
}
sum++;
if(n%20){
f(n/2); // 如果是偶数,则除以2
}else{
f(n*3+1); // 如果是奇数,则乘以3再加1
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println(“输入给定一个整数n(1<n<300)”);
int n = scan.nextInt();
int i=0;
while(true){
f(++i); // 得到角谷步数sum
if(sum
n){
System.out.println(i);
return ;
}
sum = 0;
}
}
}

72.拉丁方块填数字

/* 方块填数
“数独”是当下炙手可热的智力游戏。一般认为它的起源是“拉丁方块”,是大数学家欧拉于1783年发明的。
如图[1.jpg]所示:6×6的小格被分为6个部分(图中用不同的颜色区分),每个部分含有6个小格(以下也称为分组)。

开始的时候,某些小格中已经填写了字母(ABCDEF之一)。需要在所有剩下的小格中补填字母。 
全部填好后,必须满足如下约束: 
1. 所填字母只允许是A,B,C,D,E,F 中的某一个。 
2. 每行的6个小格中,所填写的字母不能重复。 
3. 每列的6个小格中,所填写的字母不能重复。 
4. 每个分组(参见图中不同颜色表示)包含的6个小格中,所填写的字母不能重复。 
为了表示上的方便,我们用下面的6阶方阵来表示图[1.jpg]对应的分组情况(组号为0~5):

000011
022013
221113
243333
244455
445555
用下面的数据表示其已有字母的填写情况:
02C
03B
05A
20D
35E
53F
很明显,第一列表示行号,第二列表示列号,第三列表示填写的字母。行号、列号都从0开始计算。
一种可行的填写方案(此题刚好答案唯一)为:
E F C B D A
A C E D F B
D A B E C F
F B D C A E
B D F A E C
C E A F B D
你的任务是:编写程序,对一般的拉丁方块问题求解,如果多解,要求找到所有解。
【输入、输出格式要求】
用户首先输入6行数据,表示拉丁方块的分组情况。
接着用户输入一个整数n (n<36), 表示接下来的数据行数
接着输入n行数据,每行表示一个预先填写的字母。
程序则输出所有可能的解(各个解间的顺序不重要)。
每个解占用7行。
即,先输出一个整数,表示该解的序号(从1开始),接着输出一个6×6的字母方阵,表示该解。
解的字母之间用空格分开。
如果找不到任何满足条件的解,则输出“无解”
例如:用户输入:
000011
022013
221113
243333
244455
445555
6
02C
03B
05A
20D
35E
53F
则程序输出:
1
E F C B D A
A C E D F B
D A B E C F
F B D C A E
B D F A E C
C E A F B D

再如,用户输入:
001111
002113
022243
022443
544433
555553
7
04B
05A
13D
14C
24E
50C
51A
则程序输出:
1
D C E F B A
E F A D C B
A B F C E D
B E D A F C
F D C B A E
C A B E D F
2
D C E F B A
E F A D C B
A D F B E C
B E C A F D
F B D C A E
C A B E D F
3
D C F E B A
A E B D C F
F D A C E B
B F E A D C
E B C F A D
C A D B F E
4
D C F E B A
B E A D C F
A D C F E B
F B E A D C
E F B C A D
C A D B F E
5
D C F E B A
E F A D C B
A B C F E D
B E D A F C
F D B C A E
C A E B D F
6
D C F E B A
E F A D C B
A B D F E C
B E C A F D
F D B C A E
C A E B D F
7
D C F E B A
E F A D C B
A D B F E C
B E C A F D
F B D C A E
C A E B D F
8
D C F E B A
F E A D C B
A D B C E F
B F E A D C
E B C F A D
C A D B F E
9
D C F E B A
F E A D C B
A F C B E D
B D E A F C
E B D C A F
C A B F D E
*/

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.awt.Point;
public class LTDiamonds {
static int count = 0;
// 显示矩阵
public static void show(char[][] m){
System.out.println(++count);
for(int i=0;i<m.length;i++){
for(int j=0;j<m[i].length;j++){
System.out.print(m[i][j]+” “);
}
System.out.println();
}
}
// 输入数据初始化操作
public static void init(char[][] m, char[][] gArr,
List<List> gLis) {
Scanner scan = new Scanner(System.in);
for(int i=0;i<gArr.length;i++){ // 输入分组
gArr[i] = scan.nextLine().toCharArray();
}
for(int i=0;i<gArr.length;i++){ // 初始gLis的长度为6个空list
gLis.add(new ArrayList());
}
for(int i=0;i<gArr.length;i++){ // 用 gArr 为 gLis 赋值(记录每个分组的坐标)
for(int j=0;j<gArr[i].length;j++){
gLis.get(gArr[i][j]-‘0’).add(new Point(i,j));
m[i][j] = ‘0’; // 顺便为矩阵赋初始值为全’0’
}
}
int n = scan.nextInt(); // 初始填写字母个数
scan.nextLine();
for(int i=0;i<n;i++){ // 输入初始填写的字母
char[] c = scan.nextLine().toCharArray();
m[c[0]-‘0’][c[1]-‘0’] = c[2];
}
}
// 分组检测(分组里是否存在 c)
public static boolean checkG(char[][] m,int gI,
List<List> gLis,char c){
for(int i=0;i<gLis.get(0).size();i++){
int x = gLis.get(gI).get(i).x;
int y = gLis.get(gI).get(i).y;
if(cm[x][y]){
return true;
}
}
return false;
}
// 行列(RC)检测 (是否存在 c)
public static boolean checkRC(char[][] m,char c,int row,int col){
for(int i=0;i<m.length;i++){
if(m[i][col]c){
return true;
}
if(m[row][i]c){
return true;
}
}
return false;
}
// 检测 c是否可行
public static boolean check(char[][] m, List<List> gLis, int row,
int col, int gI,int x) {
return !checkG(m,gI,gLis,(char)(‘A’+x))&& // 分组里 没有c
!checkRC(m,(char)(‘A’+x),row,col); // 行列检测 没有c
}
// 递归探测
public static void f(char[][] m,char[][] gArr,
List<List> gLis,int row,int col){
if(row
6){ // 最后一行都执行完了
show(m); // 输出
return ; // 结束并返回
}
if(m[row][col]!=‘0’){ // 不为0,说明有字母,进行下个位置探测
if(col+1
6){ // 如果列读到了最后,行加1,列=0再进行探测
f(m,gArr,gLis,row+1,0);
}else{ // 列+1,再进行探测
f(m,gArr,gLis,row,col+1);
}
}else{
for(int i=0;i<6;i++){
if(check(m,gLis,row,col,gArr[row][col]-‘0’,i)){
char temp = m[row][col]; // 暂存要替换矩阵原来的元素
m[row][col] = (char)(‘A’+i);
if(col+1
6){ // 如果列读到了最后,行加1,列=0再进行探测
f(m,gArr,gLis,row+1,0);
}else{ // 列+1,再进行探测
f(m,gArr,gLis,row,col+1);
}
m[row][col] = temp;
}
}
}
}
// 主函数
public static void main(String[] args) {
char[][] m = new char[6][6]; // 矩阵
char[][] gArr = new char[6][]; // 分组
List<List> gLis; // 记录分组的每个元素的坐标
gLis = new ArrayList<List>();
init(m, gArr,gLis); // 输入数据初始化操作
f(m,gArr,gLis,0,0); // 递归探测
}
}

73.运动员分组

/* 运动员分组
有N个人参加100米短跑比赛。跑道为8条。程序的任务是按照尽量使每组的人数相差最少的原则分组。
例如:
N=8时,分成1组即可。
N=9时,分成2组:一组5人,一组4人。
N=25时,分4组:7、6、6、6。

请编程计算分组数字。
要求从标准输入获得一个正整数(1~100之间,不必考虑输入错误的情况),表示参赛的人数。
程序输出每个组的人数。从大到小顺序输出,每个数字一行。

比如,
用户输入:25
程序输出:
7
6
6
6
*/

import java.util.Scanner;
public class AthleteGrouping {
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入一个正整数(1~100之间),表示参赛的人数。”);
int n = scan.nextInt();
int g = (n+7)/8; // 分组数 g
if(g>8) g = 8; // 超过8的直接分8组
int num = n/g; // 每组人数(g-1)个num
int r = n%g; // 分组 余数 r
for(int i=0;i<r;i++){ // 余数均分
System.out.println(num+1);
}
for(int i=0;i<g-r;i++){ // 输出剩下的
System.out.println(num);
}
}
}

74.网格中移动字母

/*
网格中移动字母
2×3=6个方格中放入ABCDE五个字母,右下角的那个格空着。如图【1.jpg】所示。 ]

和空格子相邻的格子中的字母可以移动到空格中,比如,图中的C和E就可以移动,移动后的局面分别是:

A B
D E C

A B C
D E
为了表示方便,我们把6个格子中字母配置用一个串表示出来,比如上边的两种局面分别表示为:
ABDEC
ABCD
E
题目的要求是:请编写程序,由用户输入若干表示局面的串,程序通过计算,
输出是否能通过对初始状态经过若干次移动到达该状态。可以实现输出1,否则输出0。初始状态为:ABCDE*
用户输入的格式是:先是一个整数n,表示接下来有n行状态。程序输出也应该是n行1或0
例如,用户输入:
3
ABCDE*
ABDEC
CAED
B
则程序应该输出:
1
1
0
注意:
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。
*/

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
public class NetGridMoveLetter {
// 交换元素
public static String swap(String s,int k,int j){
char[] c = s.toCharArray();
char t = c[k];
c[k] = c[j];
c[j] = t;
return new String©;
}
public static int f(String s){
ArrayList lis = new ArrayList(); // 记录全部交换结果(检查重复用)
Queue queue = new LinkedList(); // 队列(用来测试所有可能)
int[] d = {-1,-3,1,3}; // 定义方向(左,上,右,下)
queue.offer(s); // 入队
lis.add(s); // 加入记录
while(queue.size()>0){
String firstStr = queue.poll(); // 出队
if(firstStr.equals(“ABCDE*”)) return 1;// 找到结果,退出
int k = firstStr.indexOf(““); // 找到 ““号的位置
for(int i=0;i<4;i++){ // 左,上,右,下 四个方向都探测
int j = k+d[i];
if(j>=0&&j<=5){ // 当前方向不越界
String t = swap(firstStr,k,j); // 交换元素
if(!lis.contains(t)){ // lis 不包含 t
queue.offer(t); // 入队
lis.add(t); // 添加记录
}
}
}
}
return 0;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println(“输入整数n”);
int n = scan.nextInt();
scan.nextLine();
String[] s = new String[n];
for(int i=0;i<n;i++){
s[i] = scan.nextLine(); // 初始数据
}
for(int i=0;i<n;i++){
System.out.println(f(s[i])); // 得到结果
}
}
}

运行结果:
输入整数n
3
ABCDE*
ABDEC
CAED
B
1
1
0

输入整数n
3
ABCDE*
ABDEC
CAED
B
1
1
0

下边程序输出移动过程:
import java.util.ArrayList;
import java.util.Scanner;
class moveStr {
String str;
String bz;
moveStr(String str, String bz) {
this.str = str;
this.bz = bz;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getBz() {
return bz;
}
public void setBz(String bz) {
this.bz = bz;
}
}
public class CopyOfGrid {
String destStr = “ABCDE*”;// 目标字符串
ArrayList lis = new ArrayList(); // 记录结果
static boolean result = false;
// 移动字母
public String sawp(String str, int j) {
if (j < 0 || j >= str.length())
return “”;
int i = str.indexOf(“*”);
// 交换位置
char[] c = str.toCharArray();
char temp = c[i];
c[i] = c[j];
c[j] = temp;

    return new String(c);  
}  
// 检查并修改记录   
public void check(ArrayList<moveStr> list, String temp, moveStr tempMs) {  
    if (!temp.equals("") && !lis.contains(temp)) {  
        String tempBz = tempMs.bz + "->\n" + temp;  
        moveStr ms1 = new moveStr(temp, tempBz);  
        list.add(ms1);  
        lis.add(temp);  
    }  
}  
// 寻找解   
public void find(String str, String bz) {  
    ArrayList<moveStr> msLis = new ArrayList<moveStr>();  
    moveStr ms = new moveStr(str, bz);  
    msLis.add(ms);// 对象入队   
    lis.add(str);   // 把字符串加入lis   
    while (msLis.size() > 0) {  
        moveStr tempMs = msLis.remove(0);   // 出队   
        if (tempMs.str.equals(destStr)) {  
            result = true;  
            System.out.println(str + ": 有解 \n" + tempMs.bz);  
            return;  
        }  
        int k = tempMs.str.indexOf("*");    // 找到*号出现的位置   
        // 向(右)移动   
        check(msLis, sawp(tempMs.str, k + 1), tempMs);  
        // 向(上)移动   
        check(msLis, sawp(tempMs.str, k - 3), tempMs);  
        // 向(左)移动   
        check(msLis, sawp(tempMs.str, k - 1), tempMs);  
        // 向(下)移动   
        check(msLis, sawp(tempMs.str, k + 3), tempMs);  
    }  
}  
public static void main(String[] args) {  
    Scanner scan = new Scanner(System.in);  
    System.out.print("请输入目标状态字符串:");  
    String user = scan.nextLine();  
    new CopyOfGrid().find(user, user);  
    if (!result)  
        System.out.println("无解");  
}

}

import java.util.ArrayList;
import java.util.Scanner;
class moveStr {
String str;
String bz;
moveStr(String str, String bz) {
this.str = str;
this.bz = bz;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getBz() {
return bz;
}
public void setBz(String bz) {
this.bz = bz;
}
}
public class CopyOfGrid {
String destStr = “ABCDE*”;// 目标字符串
ArrayList lis = new ArrayList(); // 记录结果
static boolean result = false;
// 移动字母
public String sawp(String str, int j) {
if (j < 0 || j >= str.length())
return “”;
int i = str.indexOf(“*”);
// 交换位置
char[] c = str.toCharArray();
char temp = c[i];
c[i] = c[j];
c[j] = temp;

	return new String(c);
}
// 检查并修改记录
public void check(ArrayList<moveStr> list, String temp, moveStr tempMs) {
	if (!temp.equals("") && !lis.contains(temp)) {
		String tempBz = tempMs.bz + "->\n" + temp;
		moveStr ms1 = new moveStr(temp, tempBz);
		list.add(ms1);
		lis.add(temp);
	}
}
// 寻找解
public void find(String str, String bz) {
	ArrayList<moveStr> msLis = new ArrayList<moveStr>();
	moveStr ms = new moveStr(str, bz);
	msLis.add(ms);// 对象入队
	lis.add(str);	// 把字符串加入lis
	while (msLis.size() > 0) {
		moveStr tempMs = msLis.remove(0);	// 出队
		if (tempMs.str.equals(destStr)) {
			result = true;
			System.out.println(str + ": 有解 \n" + tempMs.bz);
			return;
		}
		int k = tempMs.str.indexOf("*");	// 找到*号出现的位置
		// 向(右)移动
		check(msLis, sawp(tempMs.str, k + 1), tempMs);
		// 向(上)移动
		check(msLis, sawp(tempMs.str, k - 3), tempMs);
		// 向(左)移动
		check(msLis, sawp(tempMs.str, k - 1), tempMs);
		// 向(下)移动
		check(msLis, sawp(tempMs.str, k + 3), tempMs);
	}
}
public static void main(String[] args) {
	Scanner scan = new Scanner(System.in);
	System.out.print("请输入目标状态字符串:");
	String user = scan.nextLine();
	new CopyOfGrid().find(user, user);
	if (!result)
		System.out.println("无解");
}

}

运行结果:
请输入目标状态字符串:ABDEC
AB
DEC: 有解
ABDEC->
ABCDE

75.国庆星期日

/* 国庆星期日
1949年的国庆节(10月1日)是星期六。
今年(2012)的国庆节是星期一。
那么,从建国到现在,有几次国庆节正好是星期日呢?
只要答案,不限手段!
可以用windows日历,windows计算器,Excel公式,。。。。。
当然,也可以编程!
不要求写出具体是哪些年,只要一个数目!
千万不要提交源代码!
答案不要写在这里,写在“解答.txt”中
*/
public class T17 {
public static int calc(int n,int m,int d){
int[][] days = {{0,31,28,31,30,31,30,31,31,30,31,30,31}, // 平年
{0,31,29,31,30,31,30,31,31,30,31,30,31}};// 闰年
int b = 0; // 默认为平年
if(n%40&&n%100!=0||n%4000) b = 1; // 是闰年
int sum = d;
for(int i=0;i<m;i++){
sum += days[b][i];
}
return sum;
}
public static void main(String[] args){
int count = 0;
// 1949年的国庆节(10月2日)是星期日。
// 得到这年10月2号后的的剩余天数
int total = calc(1949,12,31)-calc(1949,10,2);
for(int i=1950;i<2012;i++){
// calc(i)计算每年的10月1日是这一年的第天数,再用总天数对7取余0说明是周日
total += calc(i,10,1); // 计算当年到10月1的总天数
if(total%7
0){
System.out.println(i+“年10月1日”);
count++; // 次数加1
}
}
System.out.println(“总数:”+count);
}
}

76.取字母组成串

/* 取字母组成串

  • A B C D中取5次,每个字母都可以重复取出,形成一个串。
    现在要求,串中A出现的次数必须为偶数(0次也算偶数)。
    求可以形成多少种可能的串。
    */
    public class 取字母组成串 {
    // 取n次,A出现奇数次
    public static int g(int n) {
    if (n == 1)
    return 1;
    return 3 * g(n – 1) + f(n – 1);
    }
    // 取n次,A出现偶次
    public static int f(int n) {
    if (n == 1)
    return 3;
    return 3 * f(n – 1) + g(n – 1);
    }
    public static void main(String[] args) {
    System.out.println(f(5));
    }
    }

77.有理数的循环节

/* 有理循环小数
1/7 = 0.142857142… 是个无限循环小数。
任何有理数都可以表示为无限循环小数的形式。
本题目要求即是:给出一个数字的循环小数表示法。
例如:
输入:
1,5
则输出:
0.2

输入:
1,7
则输出:
0.[142857]
输入:
7,6
则输出:
1.1[6]
用户输入的格式是:
整数,整数
每个整数范围均为:1~1000
程序输出两个整数做除法产生的小数或无限循环小数(循环节用方括号括起)。
*/
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;

public class 有理数的循环节 {
public static String f(int m,int n){
StringBuffer sb = new StringBuffer(); // 保存结果
List lis = new ArrayList(); // 记录所有余数
String s = m/n+“.”; // 保存整数部分
m = m%n; // 得到余数
while(m!=0){
if(lis.contains(m)){
int i=0; // 得到循环节开始的位置 i
for(;i<sb.length();i++){
if(sb.charAt(i)-‘0’==m10/n){
break;
}
}
sb.insert(i,“[”); // 为循环节添加”[ ]”
sb.insert(sb.length(),“]”);
break;
}else{
lis.add(m); // 添加商
sb.append(m
10/n); // 添加结果元素
}
m = m*10%n; // 得到余数
}
return sb.insert(0, s).toString();
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“整数范围均为:1~1000(格式: 整数,整数 )”);
String s = scan.nextLine();
String[] ss = s.split(“,”);
int m = Integer.parseInt(ss[0]);
int n = Integer.parseInt(ss[1]);
System.out.println(f(m,n));
}
}

78.正六面体染色

/* 正六面体染色
正六面体用4种颜色染色。
共有多少种不同的染色样式?
要考虑六面体可以任意旋转、翻转。
/
import java.util.ArrayList;
public class 正六面体染色 {
public static int sum = 0;
/
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
f();
}

public static void f(){  
    ArrayList<Integer> arr = new ArrayList<Integer>(4*4*4*4*4*4);  
    for(int x1 = 1; x1 <= 4; x1++){  
        for(int x2 = 1; x2 <= 4; x2++){  
            for(int x3 = 1; x3 <= 4; x3++){  
                for(int x4 = 1; x4 <= 4; x4++){  
                    for(int x5 = 1; x5 <= 4; x5++){  
                        for(int x6 = 1; x6 <= 4; x6++){  
                            arr.add(x1 * 100000 + x2 * 10000 + x3 * 1000 + x4 * 100 + x5 * 10 + x6);  
                        }  
                    }  
                }  
            }  
        }  
    }  

    for(int x1 = 1; x1 <= 4; x1++){  
        for(int x2 = 1; x2 <= 4; x2++){  
            for(int x3 = 1; x3 <= 4; x3++){  
                for(int x4 = 1; x4 <= 4; x4++){  
                    for(int x5 = 1; x5 <= 4; x5++){  
                        for(int x6 = 1; x6 <= 4; x6++){  
                            if(arr.contains(x1 * 100000 + x2 * 10000 + x3 * 1000 + x4 * 100 + x5 * 10 + x6)){  
                                sum++;  
                                arr.remove(new Integer(x1 * 100000 + x2 * 10000 + x3 * 1000 + x4 * 100 + x5 * 10 + x6));  
                                up(x4,x1,x3,x6,x5,x2,arr);  
                                left(x5,x2,x1,x4,x6,x3,arr);  
                                rotate(x1,x5,x2,x3,x4,x6,arr);  
                            }  
                        }  
                    }  
                }  
            }  
        }  
    }  
    System.out.println(sum);  
}  
  
public static void up(int x1, int x2, int x3, int x4, int x5, int x6, ArrayList<Integer> arr){  
    if(arr.remove(new Integer(x1 * 100000 + x2 * 10000 + x3 * 1000 + x4 * 100 + x5 * 10 + x6))){  
            up(x4,x1,x3,x6,x5,x2,arr);  
            left(x5,x2,x1,x4,x6,x3,arr);  
            rotate(x1,x5,x2,x3,x4,x6,arr);  
    }else  
        return;   
}  
  
public static void left(int x1, int x2, int x3, int x4, int x5, int x6, ArrayList<Integer> arr){  
    if(arr.remove(new Integer(x1 * 100000 + x2 * 10000 + x3 * 1000 + x4 * 100 + x5 * 10 + x6))){  
            up(x4,x1,x3,x6,x5,x2,arr);  
            left(x5,x2,x1,x4,x6,x3,arr);  
            rotate(x1,x5,x2,x3,x4,x6,arr);  
    }else  
            return;   
}  

public static void rotate(int x1, int x2, int x3, int x4, int x5, int x6, ArrayList<Integer> arr){  
    if(arr.remove(new Integer(x1 * 100000 + x2 * 10000 + x3 * 1000 + x4 * 100 + x5 * 10 + x6))){  
            up(x4,x1,x3,x6,x5,x2,arr);  
            left(x5,x2,x1,x4,x6,x3,arr);  
            rotate(x1,x5,x2,x3,x4,x6,arr);  
    }else  
            return;   
}

}

79.三角螺旋阵

/* 三角螺旋阵
方阵的主对角线之上称为“上三角”。
请你设计一个用于填充n阶方阵的上三角区域的程序。填充的规则是:使用1,2,3….的自然数列,从左上角开始,按照顺时针方向螺旋填充。
例如:当n=3时,输出:
1 2 3
6 4
5
当n=4时,输出:
1 2 3 4
9 10 5
8 6
7
当n=5时,输出:
1 2 3 4 5
12 13 14 6
11 15 7
10 8
9
程序运行时,从标准输入获得整数n(3~20)
程序输出:方阵的上三角部分。
要求格式:每个数据宽度为4,右对齐。

*/
import java.util.Scanner;

public class 三角螺旋阵 {
// 输出
public static void print(int[][] m){
for(int[] x:m){
for(int y:x){
System.out.printf(“%4d”,y);
}
System.out.println();
}
}
// 初始化
public static void init(int[][] m){
for(int i=0;i<m.length;i++){
m[i] = new int[m.length-i];
}
}
// 螺旋填充数字
public static void f(int[][] m,int k,int num){
if(k>=m.length/2) return ;
// 第一行
for(int i=k;i<m[k].length-k;i++){
m[k][i] = num++;
}
// 最后一位
for(int i=k+1;i<m[k].length-k;i++){
m[i][m[i].length-1-k] = num++;
}
// 左列
for(int i=m[k].length-2-k;i>k;i–){
m[i][k] = num++;
}
f(m,k+1,num); // 递归进行内圈填充
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入整数n(3~20)”);
int n = scan.nextInt();
int[][] m = new int[n][];
init(m); // 初始化
f(m,0,1); // 螺旋填充数字
print(m); // 输出
}
}

80.机器人行走

/*机器人行走

  • 【编程题】(满分18分)
    某少年宫引进了一批机器人小车。可以接受预先输入的指令,按指令行动。小车的基本动作很简单,
    只有3种:左转(记为L),右转(记为R),向前走若干厘米(直接记数字)。
    例如,我们可以对小车输入如下的指令:
    15L10R5LRR10R20
    则,小车先直行15厘米,左转,再走10厘米,再右转,…
    不难看出,对于此指令串,小车又回到了出发地。
    你的任务是:编写程序,由用户输入指令,程序输出每条指令执行后小车位置与指令执行前小车位置的直线距离。
    【输入、输出格式要求】
    用户先输入一个整数n(n<100),表示接下来将有n条指令。
    接下来输入n条指令。每条指令只由L、R和数字组成(数字是0~100之间的整数)
    每条指令的长度不超过256个字符。
    程序则输出n行结果。
    每条结果表示小车执行相应的指令前后位置的直线距离。要求四舍五入到小数后2位。
    例如:用户输入:
    5
    L100R50R10
    3LLL5RR4L12
    LL
    100R
    5L5L5L5
    则程序输出:
    102.96
    9.06
    0.00
    100.00
    0.00
    */

import java.util.Scanner;

public class Demo02 {
static int direction = 1;
// direction的值 左为0,上为1,右为2,下为3
static int[] X = {-1, 0, 1, 0};
static int[] Y = { 0, 1, 0, -1};
static int x = 0; // 点坐标 x 值
static int y = 0; // 点坐标 y 值
// 输入数据
public static String[] input(int n){
Scanner scan = new Scanner(System.in);
String[] ss = new String[n];
for(int i=0;i<n;i++){
ss[i] = scan.nextLine();
}
return ss;
}
// 计算xy坐标值
public static void countXY(String ss) {
if(!ss.equals(“”)){
int n = Integer.parseInt(ss);
x += n * X[direction];
y += n * Y[direction];
}
}
// 修改方向(direction)
public static void alterDirection(char c){
if(c==‘L’){ // direction的值 左为0,上为1,右为2,下为3
direction = (direction+3)%4;
}else if(c==‘R’){
direction = (direction+1)%4;
}
}
// 进入函数操作
public static void f(String s){
String ss=“”; // 暂存数字
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(c>=‘0’&&c<=‘9’){
ss += c; // 添加数字
}else {
countXY(ss);// 计算xy坐标值
ss = “”; // 清空用过的数字
alterDirection©; // 修改方向(direction)
}
}
countXY(ss); // for 执行完查看暂存数字是否还有数字,有的话计算最后一次坐标
ss = “”; // 清空用过的数字
}
// 计算xy点与原点的距离,并输出
public static void calc(){
System.out.printf(“%.2f\n”,Math.sqrt(xx+yy));
x = 0; // 回归原点 为下次计算用
y = 0;
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
String[] s = input(scan.nextInt()); // 输入数据
for(int i=0;i<s.length;i++){
f(s[i]); // 进入函数操作
calc(); // 计算xy点与原点的距离,并输出
}
}
}

运行结果:
5
L100R50R10
3LLL5RR4L12
LL
100R
5L5L5L5
102.96
9.06
0.00
100.00
0.00

81.土地测量

/*土地测量
造成高房价的原因有许多,比如土地出让价格。既然地价高,土地的面积必须仔细计算。
遗憾的是,有些地块的形状不规则,比如是如图【1.jpg】中所示的五边形。
一般需要把它划分为多个三角形来计算。
已知三边求三角形的面积需要用海伦定理,参见【2.jpg】

各条边长数据如下: 
AB = 52.1 
BC = 57.2 
CD = 43.5 
DE = 51.9 
EA = 33.4 
EB = 68.2 
EC = 71.9 
根据这些数据求五边形地块的面积。四舍五入到小数后两位。只写结果,不要源代码! 
答案写在“解答.txt”中,不要写在这里!

/
public class Demo01 {
public static void main(String[] args) {
float AB = 52.1f;
float BC = 57.2f;
float CD = 43.5f;
float DE = 51.9f;
float EA = 33.4f;
float EB = 68.2f;
float EC = 71.9f;
float s = 0f;
float a = (AB+EB+EA)/2; // 半周长a
float b = (BC+EC+EB)/2; // 半周长b
float c = (CD+DE+EC)/2; // 半周长c
s += Math.sqrt(a
(a-AB)(a-EB)(a-EA));
s += Math.sqrt(b*(b-BC)(b-EC)(b-EB));
s += Math.sqrt(c*(c-CD)(c-DE)(c-EC));
System.out.println(new DecimalFormat(“.00”).format(s));
}
}

运行结果:
3789.86

82.打印回型嵌套

/*


  •     *







  •     *

观察这个图形,它是由一系列正方形的星号方框嵌套而成。
在上边的例子中,最外方框的边长为11。
本题的任务就是从标准输入获得一个整数n(1<n<100)
程序则生成嵌套着的回字型星号方框。其最外层方框的边长为n
例如:
输入:
5
程序输出:




输入:6
程序输出:





/
import java.util.Scanner;
public class Demo04 {
// 显示数组
public static void show(char[][] c){
for(char[] x:c){
for(char y:x){
System.out.print(y);
}
System.out.println();
}
}
// 初始化数组为空数组
public static void init(char[][] c){
for(int i=0;i<c.length;i++){
for(int j=0;j<c.length;j++){
c[i][j] = ’ ‘;
}
}
}
public static void oper(char[][] c,int n,int start){
if(start>=n) return;
for(int i=start;i<n;i++){ // 赋值第一行为’
’ 上
c[start][i] = ‘‘;
}
for(int i=start;i<n;i++){ // 赋值最后一行为’
’ 下
c[n-1][i] = ‘‘;
}
for(int i=start;i<n;i++){ // 赋值左一列为’
’ 左
c[i][start] = ‘‘;
}
for(int i=start;i<n;i++){ // 赋值右一列为’
’ 右
c[i][n-1] = ‘*’;
}
oper(c,n-2,start+2); // 矩阵范围 缩小2 ,起始赋值位置 加2
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println(“输入获得一个整数n(1<n<100)”);
int n = scan.nextInt();
char[][] c = new char[n][n];
init©; // 初始化数组为空数组
oper(c,n,0); // 赋值
show©; // 显示数组
}
}

运行结果:
输入获得一个整数n(1<n<100)
13


  •       *









  •       *

83.夺冠概率模拟

/*夺冠概率
足球比赛具有一定程度的偶然性,弱队也有战胜强队的可能。
假设有甲、乙、丙、丁四个球队。根据他们过去比赛的成绩,得出每个队与另一个队对阵时取胜的概率表:
甲 乙 丙 丁
甲 乙 丙 丁
甲 – 0.1 0.3 0.5
乙 0.9 – 0.7 0.4
丙 0.7 0.3 – 0.2
丁 0.5 0.6 0.8 –
数据含义:甲对乙的取胜概率为0.1,丙对乙的胜率为0.3,…
现在要举行一次锦标赛。双方抽签,分两个组比,获胜的两个队再争夺冠军。(参见【1.jpg】)
请你进行10万次模拟,计算出甲队夺冠的概率。

注意: 
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!

/
import java.util.Random;
import java.text.DecimalFormat;
public class Demo05 {
public static void main(String[] args){
// (a vs b)a 表示 (a队与b队)对战,a队 胜的概率
// (a vs b)a
(c vs d)c*(a vs c)a + (a vs b)1*(c vs d)d*(a vs d)a
// 把1看作a
double ab_cd = 0.10.20.3+0.10.80.5; // ab_cd 代表 (a vs b)a (a vs c)+(a vs d)=a的概率
double ac_bd = 0.30.40.1+0.30.60.5; // ac_bd 代表 (a vs c)a (a vs b)+(a vs d)=a的概率
double ad_bc = 0.50.70.1+0.50.30.3; // ad_bc 代表 (a vs d)a (a vs b)+(a vs c)=a的概率
double sum = 0; // 总计
Random r = new Random(3); // 随机对象 r
int n = 100000; // 循环次数
for(int i=0;i<n;i++){ // 10万次模拟
switch(r.nextInt(3)){
case 0: sum += ab_cd; break;
case 1: sum += ac_bd; break;
case 2: sum += ad_bc; break;
}
}
System.out.println(new DecimalFormat(“#.###”).format(sum/n));
}
}

运行结果:
0.076

84.二阶魔方旋转

/* 二阶魔方旋转
魔方可以对它的6个面自由旋转。
我们来操作一个2阶魔方(如图1所示):
为了描述方便,我们为它建立了坐标系。

各个面的初始状态如下:
x轴正向:绿
x轴反向:蓝
y轴正向:红
y轴反向:橙
z轴正向:白
z轴反向:黄

假设我们规定,只能对该魔方进行3种操作。分别标记为:
x 表示在x轴正向做顺时针旋转
y 表示在y轴正向做顺时针旋转
z 表示在z轴正向做顺时针旋转

xyz 则表示顺序执行x,y,z 3个操作

题目的要求是:
从标准输入获得一个串,表示操作序列。
程序输出:距离我们最近的那个小方块的3个面的颜色。
顺序是:x面,y面,z面。

例如:在初始状态,应该输出:
绿红白

初始状态下,如果用户输入:
x
则应该输出:
绿白橙

初始状态下,如果用户输入:
zyx
则应该输出:
红白绿

请编程实现所述功能。
*/
import java.util.Scanner;

public class Demo06 {
// x旋转操作
public static void xSpin(char[] xf, char[] yf, char[] ya, char[] zf,
char[] za) {
char yf0 = yf[0];
char yf2 = yf[2];
char ya0 = ya[0];
char ya2 = ya[2];
// 修改y的前后面
yf[0] = zf[0];
yf[2] = zf[2];
ya[0] = za[0];
ya[2] = za[2];
// 修改z的前后面
zf[0] = ya0;
zf[2] = ya2;
za[0] = yf0;
za[2] = yf2;
// 修改x前面
char xf0 = xf[0];
xf[0] = xf[2];
xf[2] = xf[3];
xf[3] = xf[1];
xf[1] = xf0;
}
// y旋转操作
public static void ySpin(char[] xf, char[] xa, char[] yf, char[] zf,
char[] za) {
char zf2 = zf[2];
char zf3 = zf[3];
char za0 = za[0];
char za1 = za[1];
// 修改z的前后面
zf[2] = xf[3];
zf[3] = xf[1];
za[1] = xa[2];
za[0] = xa[3];
// 修改x的前后面
xa[2] = zf2;
xa[3] = zf3;
xf[1] = za0;
xf[3] = za1;
// 修改y前面
char yf0 = yf[0];
yf[0] = yf[2];
yf[2] = yf[3];
yf[3] = yf[1];
yf[1] = yf0;
}
// z旋转操作
public static void zSpin(char[] xf, char[] xa, char[] yf, char[] ya,
char[] zf) {
char xf0 = xf[0];
char xf1 = xf[1];
char xa2 = xa[2];
char xa0 = xa[0];
// 修改x的前后面
xf[0] = yf[0];
xf[1] = yf[1];
xa[0] = ya[2];
xa[2] = ya[3];
// 修改y的前后面
yf[0] = xa2;
yf[1] = xa0;
ya[3] = xf0;
ya[2] = xf1;
// 修改z前面
char zf0 = zf[0];
zf[0] = zf[2];
zf[2] = zf[3];
zf[3] = zf[1];
zf[1] = zf0;
}
public static void main(String[] args){
char[] xf = {‘绿’,‘绿’,‘绿’,‘绿’}; // x前
char[] xa = {‘蓝’,‘蓝’,‘蓝’,‘蓝’}; // x后

    char[] yf = {'红','红','红','红'};  // y前   
    char[] ya = {'橙','橙','橙','橙'};  // y后   
      
    char[] zf = {'白','白','白','白'};  // z前   
    char[] za = {'黄','黄','黄','黄'};  // z后   
      
    Scanner scan = new Scanner(System.in);  
    System.out.println("输入关于xyz的字符串");  
    String s = scan.nextLine();  
    char[] c = s.toCharArray(); // 输入的数据以每个字符来操作   
    for(int i=0;i<c.length;i++){  
        switch(c[i]){  
            case 'x': { // x旋转操作   
                xSpin(xf, yf, ya, zf, za);  
            }break;  
            case 'y': { // y旋转操作   
                ySpin(xf, xa, yf, zf, za);  
            }break;  
            case 'z': { // z旋转操作   
                zSpin(xf, xa, yf, ya, zf);  
            }break;  
        }  
    }  
    System.out.println(xf[1]+""+yf[0]+""+zf[2]);  
}

}

运行结果:
输入关于xyz的字符串
zyx
红白绿

85.砝码称重

/*砝码称重
5个砝码
用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量。
如果只有5个砝码,重量分别是1,3,9,27,81。则它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中)。
本题目要求编程实现:对用户给定的重量,给出砝码组合方案。
例如:
用户输入:
5
程序输出:
9-3-1
用户输入:
19
程序输出:
27-9+1

要求程序输出的组合总是大数在前小数在后。
可以假设用户的输入的数字符合范围1~121。
/
import java.util.Scanner;
public class Demo07 {
public static void f(int n) {
int[] sign = new int[]{-1,0,1}; // 定义符号
StringBuffer sb = new StringBuffer();
for(int a:sign){
for(int b:sign){
for(int c:sign){
for(int d:sign){
for(int e:sign){
int i = a
1;
int j = b3;
int k = c
9;
int l = d27;
int m = e
81;
if(i+j+k+l+m==n){ // 找到结果
// 如果不为0,则添加元素,并在”正数”前添加”+“号
sb.append(m!=0?(m>0?”+“+m:m):”“);
sb.append(l!=0?(l>0?”+“+l:l):”“);
sb.append(k!=0?(k>0?”+“+k:k):”“);
sb.append(j!=0?(j>0?”+“+j:j):”“);
sb.append(i!=0?(i>0?”+“+i:i):”“);
sb.deleteCharAt(0); // 去掉首元素的”+”号;
System.out.println(sb);
return;
}
}
}
}
}
}
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入重量(1到121)之间任意整数”);
int n = scan.nextInt(); // 输入重量
f(n);
}
}

运行结果:
19
27-9+1

86.公式解析

/*公式解析
在某些应用中,为了支持灵活性,往往用到自定义的公式。
比如,有如下的原始公式集合:
int add(int x, int y): 返回x与y的和
int add(int x, int y, int z): 返回x,y,z三个数的和
int min(int x, int y): 返回x,y中较小的值
int max(int x, int y): 返回x,y中较大的值
int doubleMe(int x): 返回 x 的2倍
给出一个自定义公式串
add(min(5,3),max(2,8),add(1,doubleMe(1)))
通过手工计算可以得出结果为:14
本题的任务是:编写一个解析程序,能够对由上述原始公式任意组合出来的公式计算其结果。
也就是输入一个自定义公式串,输出它的计算结果(可以不考虑输入公式本身有语法错误的情况)。
输入的公式串中可以含有多余的空格,类似:
add( min(5, 3) , max(2 , 8) ) 也是合法的公式。

程序输入:公式串
程序输出:该公式的计算值
*/
分析:

import java.util.Scanner;
import java.util.Stack;

public class Demo08 {
// add 返回x与y的和
public static int add(int x,int y){
return x+y;
}
// add 返回x,y,z三个数的和
public static int add(int x,int y,int z){
return x+y+z;
}
// min 返回x,y中较小的值
public static int min(int x, int y){
return x<y?x:y;
}
// max 返回x,y中较大的值
public static int max(int x, int y){
return x>y?x:y;
}
// doubleMe 返回 x 的2倍
public static int doubleMe(int x){
return x*2;
}
public static int check(String s){
Stack method = new Stack(); // 保存方法名
Stack bracket = new Stack();// 保存对应括号
Stack num = new Stack(); // 保存数字
Stack count = new Stack(); //保存参数个数

    StringBuffer ss = new StringBuffer();   // 添加字母   
    StringBuffer nn = new StringBuffer();   // 添加数字   
    for(int i=0;i<s.length();i++){  
        char c = s.charAt(i);  
        if(c>='A'&&c<='Z'||c>='a'&&c<='z'){  
            ss.append(c);   // 拼凑方法名   
        }else if(c=='('){  
            method.push(ss.toString()); // 方法名拼凑完成,添加到栈   
            count.push(0);  
            ss.setLength(0);    // 放入方法,并清空临时串   
            bracket.push(')');  
        }else if(c>='0'&&c<='9'){  
            nn.append(c);   // 拼凑数字   
        }else if(nn.length()!=0){  
            num.push(nn.toString());    // 数字名拼凑完成,添加到栈   
            count.push(count.pop()+1);  // 参数个数加1   
            nn.setLength(0);  
        }  
        if(c==')'){  
            String m = method.pop();    // 得到方法   
            int[] n = new int[count.pop()]; // 依参数个数开辟数组   
            for(int j=0;j<n.length;j++){ // 得到每个参数   
                n[j] = Integer.parseInt(num.pop());  
            }  
            bracket.pop();  // 去一层括号   
            if("add".equals(m)){  
                if(n.length==2){    // add() 两个参数   
                    num.push(""+add(n[1],n[0]));  
                }else if(n.length==3){  // add() 三个参数   
                    num.push(""+add(n[2],n[1],n[0]));  
                }  
            }else if("min".equals(m)){  // min()   
                num.push(""+min(n[1],n[0]));  
            }else if("max".equals(m)){  // max()   
                num.push(""+max(n[1],n[0]));  
            }else if("doubleMe".equals(m)){ // doubleMe()   
                num.push(""+doubleMe(n[0]));  
            }  
            if(count.size()!=0){    // 如果不是最外层   
                count.push(count.pop()+1);  
            }  
        }  
    }  
    return Integer.parseInt(num.pop()); // 返回最后的结果数据   
}  
public static void main(String[] args){  
    Scanner scan = new Scanner(System.in);  
    System.out.println("输入公式串");  
    String s = scan.nextLine();  
    System.out.println(check(s));  
}

}

运行结果:
输入公式串
add(min(5,3),max(2,8),add(1,doubleMe(1)))
14

87.购物券消费方案

/* 购物券消费方案
公司发了某商店的购物券1000元,限定只能购买店中的m种商品。
每种商品的价格分别为m1,m2,…,要求程序列出所有的正好能消费完该购物券的不同购物方法。
程序输入:
第一行是一个整数m,代表可购买的商品的种类数。
接下来是m个整数,每个1行,分别代表这m种商品的单价(0<m<1000)。
程序输出:
第一行是一个整数,表示共有多少种方案
第二行开始,每种方案占1行,表示对每种商品购买的数量,中间用空格分隔。
例如:

输入:
2
200
300
则应输出:
2
2 2
5 0

输入:
2
500
800
则应输出:
1
2 0

输入:
1
999
则应输出:
0

多个方案间的顺序不重要。
*/
import java.util.Arrays;
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;

public class Demo09 {
static int[] temp; // 保存每次的结果,用来比较与下次的结果是否相同
static List<int[]> lis = new ArrayList<int[]>();
public static void print(){
for(int[] x:lis){
for(int y:x){
System.out.print(y+” “);
}
System.out.println();
}
}
// 上次记录的结果,和当前这次记录比较是否相同
public static boolean compare(int[] t){
if(tempnull) return false;
for(int i=0;i<t.length;i++){
if(temp[i]!=t[i]) return false;
}
return true;
}
// 检测符合条件的组合
public static boolean check(int[] n,int[] t){
int sum = 0;
for(int i=0;i<n.length;i++){
sum += t[i]*n[i];
}
if(sum
1000){
return true;
}
return false;
}
public static void f(int[] n,int[] b,int[] t,int count){
if(count>=b.length) return;
for(int i=0;i<=b[count];i++){
t[count] = i; // 保存当前i的值
f(n,b,t,count+1); // 迭代
if(!compare(t)){ // 去重
if(check(n,t)){ // 检测符合条件的组合 将数组添加到lis列表
lis.add(Arrays.copyOf(t, t.length));
}
}// 用temp记录结果,下次比较是否相同用(去重)
temp = Arrays.copyOf(t, t.length);
}
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入商品的种类数”);
int num = scan.nextInt();
int[] n = new int[num]; // 保存商品价格
int[] b = new int[num]; // 保存每个商品最多有几个
for(int i=0;i<num;i++){
n[i] = scan.nextInt(); // 输入每个商品价格
b[i] = 1000/n[i]; // 记录每商品的个数
}
f(n,b,new int[num],0);
if(lis.size()==0){ // 没有元素
System.out.println(0);
}else{
System.out.println(lis.size()); // 元素个数
print(); // 输出结果
}
}
}

运行结果:
输入商品的种类数
2
200
300
2
2 2
5 0

88.找素数

  • 找素数
  • 素数就是不能再进行等分的整数。比如:7,11。而9不是素数,因为它可以平分为3等份。
  • 一般认为最小的素数是2,接着是3,5,…
    请问,第100002(十万零二)个素数是多少?
    请注意:“2” 是第一素数,“3” 是第二个素数,依此类推。
    不需要提交源代码,只要写出准确的结果即可!
    答案写在:“解答.txt”中,不要写在这里。
    */

public class T18 {
// 检查是否素数
public static boolean check(int n){
for(int i=2;i*i<=n;i++){
if(n%i==0){
return false;
}
}
return true;
}
public static void main(String[] args) {
int n = 1;
int i = 3;
while(n<100002){
if(check(i)){
n++;
System.out.println(n+“->”+i);
i++;
}else{
i++;
}
}
}
}

运行结果:
.
.
.
.
99989->1299533
99990->1299541
99991->1299553
99992->1299583
99993->1299601
99994->1299631
99995->1299637
99996->1299647
99997->1299653
99998->1299673
99999->1299689
100000->1299709
100001->1299721
100002->1299743

89.除去次方数

/* 除去次方数

  • 自然数的平方数是:1 4 9 16 25 …
    自然数的立方数是:1 8 27 64 125 …
    自然数的4次方数是:1 16 81 256 …

    这些数字都可以称为次方数。
    1~10000中,去掉所有的次方数,还剩下多少个数字?

*/
import java.util.Set;
import java.util.HashSet;
public class T05 {
public static void main(String[] args){
Set sets = new HashSet();
sets.add(1.0); // 添加第一个元素 1
int i,j=2;
for(i=2;Math.pow(i, j)<=10000;i++){
for(j=2;Math.pow(i, j)<=10000;j++){
sets.add(Math.pow(i, j));
}
j = 2;
}
System.out.println(10000-sets.size());
}
}

运行结果:
9875

90.欧拉与鸡蛋

/*欧拉与鸡蛋
大数学家欧拉在集市上遇到了本村的两个农妇,每人跨着个空篮子。
她们和欧拉打招呼说两人刚刚卖完了所有的鸡蛋。
欧拉随便问:“卖了多少鸡蛋呢?”
不料一个说:“我们两人自己卖自己的,一共卖了150个鸡蛋,虽然我们卖的鸡蛋有多有少,
但刚好得了同样的钱数。你猜猜看!”
欧拉猜不出。
另一个补充道:“如果我按她那样的价格卖,可以得到32元;如果她按我的价格卖,可以得到24.5元”。
欧拉想了想,说出了正确答案。

我们不是数学家,懒得列出公式来分析。但计算机可以“暴力破解”,
就是把所有可能情况都试验一遍,撞上为止!
请写出每人鸡蛋的数目(顺序不限),用逗号隔开。

答案写在“解答.txt”中,不要写在这里!
*/
public class T11 {
public static void main(String[] args) {
for(int i=0;i<150;i++){
int x = i; // 得到两个数 x, y
int y = 150 – i;

        double priceX = 24.5/y; // 得到 x的单价   
        double priceY = 32.0/x; // 得到 y的单价   
          
        double moneyX = priceX * x; // x卖的总钱总   
        double moneyY = priceY * y; // y卖的总钱总   
          
        if(Math.abs(moneyX-moneyY)<0.000001){    // 浮点数相等比较   
            System.out.println(i+" "+(150-i));  
        }  
    }  
}

}

91.排座位

/* 排座位
要安排:3个A国人,3个B国人,3个C国人坐成一排。
要求不能使连续的3个人是同一个国籍。
求所有不同方案的总数?
*/
public class T13 {
static int sum = 0; // 不同方案总个数
// 检查是否有同一国人连续3个
public static boolean check(char[] c){
int count = 1; // 初始个数
for(int i=0;i<c.length-1;i++){
if(c[i]==c[i+1]){
count++;
}else{
count = 1; // 初始个数
}
if(count>=3) return true;
}
return false;
}
// 全排列
public static void allSort(char[] c,int start,int end){
if(start>end){
if(!check©){ // 检查是否有同一国人连续3个
sum++; // 不同方案总个数加1
}
return ;
}else{
for(int i=start;i<=end;i++){
char temp = c[i];
c[i] = c[start];
c[start] = temp;
allSort(c,start+1,end); // 递归
temp = c[i];
c[i] = c[start];
c[start] = temp;
}
}
}
public static void main(String[] args){
char[] c = {‘A’,‘A’,‘A’,‘B’,‘B’,‘B’,‘C’,‘C’,‘C’};
allSort(c,0,c.length-1); // 全排列
System.out.println(sum);
}
}

运行结果:
283824

92.m个字符的n个字符排列

/*

  • 1~9个数中的n位数全排列
    */
    import java.util.ArrayList;
    import java.util.List;

public class T05 {
static int count = 0; // 总个数
/**
* 全排列
* @param lis 记录组合
* @param start 为0~9(lis所用的下标)
* @param end 为9
*/
public static void f(List lis,int start){
if(start>=lis.size()){
System.out.println(lis); // 输出排列组合
count++; // 计数
return ;
}
for(int i=1;i<=9;i++){
if(!lis.contains(i)){
lis.set(start, i); // 修改元素
}else{
continue;
}
f(lis,start+1); // 递归修改每个元素
lis.set(start, -1); // 还原
}
}
public static void main(String[] args){
int n = 5; // 1~9个数中选5个全排列
List lis = new ArrayList();
for(int i=0;i<n;i++){ // 初始化lis长度
lis.add(-1);
}
f(lis,0); // 全排列
System.out.println(“总个数:”+count);
}
}

运行结果:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 6]
[1, 2, 3, 4, 7]
[1, 2, 3, 4, 8]
[1, 2, 3, 4, 9]
[1, 2, 3, 5, 4]

[9, 8, 7, 5, 6]
[9, 8, 7, 6, 1]
[9, 8, 7, 6, 2]
[9, 8, 7, 6, 3]
[9, 8, 7, 6, 4]
[9, 8, 7, 6, 5]
总个数:15120

方法二:对以上程序的 (数字排列)扩展为(字符排列)看下程序:
import java.util.ArrayList;
import java.util.List;

public class T13 {
static int count = 0; // 记录个数
// m排n全排列
public static void f(List lis,char[] c,int n){
if(n==0){
count++; // 记录个数
System.out.println(lis); // 输出
return ;
}
for(int i=0;i<c.length;i++){
if(!lis.contains(c[i])){ // 不包含,则添加
lis.set(lis.size()-n, c[i]);
}else{ // 否则跳过
continue;
}
f(lis,c,n-1); // 递归
lis.set(lis.size()-n, ‘0’); // 还原
}
}
public static void main(String[] args) {
long star = System.currentTimeMillis();
int n = 3; // 任选n个字符的排列组合
char[] c = “123456789”.toCharArray(); // 要排列的字符
List lis = new ArrayList();
for(int i=0;i<n;i++){
lis.add(‘0’); // 初始化 lis 的长度
}
f(lis,c,n); // 进入全排列
System.out.println(“排列个数:”+count);
System.out.println(“花费时间:”+(System.currentTimeMillis()-star)+“毫秒”);
}
}

运行结果:
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 2, 6]
[1, 2, 7]
[1, 2, 8]
[1, 2, 9]
[1, 3, 2]

[9, 7, 8]
[9, 8, 1]
[9, 8, 2]
[9, 8, 3]
[9, 8, 4]
[9, 8, 5]
[9, 8, 6]
[9, 8, 7]
排列个数:504
花费时间:19毫秒

方法三:
/*

  • m个字符的n个字符排列
    */
    import java.util.ArrayList;
    import java.util.List;

public class m个字符的n个字符排列 {
private static char[] is = new char[] { ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’};
private static int total;
private static int m = 4;
private void plzh(String s, List iL, int m) {
if(m == 0) {
System.out.println(s);
total++;
return;
}
List iL2;
for(int i = 0; i < is.length; i++) {
iL2 = new ArrayList();
iL2.addAll(iL);
if(!iL.contains(i)) {
String str = s + is[i];
iL2.add(i);
plzh(str, iL2, m-1);
}
}
}
public static void main(String[] args) {
List iL = new ArrayList();
new m个字符的n个字符排列().plzh(“”, iL, m);
System.out.println(“total : ” + total);
}
}

运行结果:
1234
1235
1236
1237
1238
1239
1243

9867
9871
9872
9873
9874
9875
9876
total : 3024

93.画表格

/*
在图形环境中很容易做出漂亮的表格。但在控制台环境中就比较困难了。
有的时候可以用一些符号大略地模拟:(word文档中可能不整齐,拷贝到记事本中看)
±——±—–+
|abc |xyz=tt|
±——±—–+
|hellomm|t2 |
±——±—–+
本题目要求设计一个程序,把用户输入的内容用这种“准表格”的方式展现出来。具体的要求是:
用户输入的第一行是一个整数,表示接下来有多少行信息。接下来的每行由若干单元组成。单元间用逗号分开。
程序输出:用表格方式重新展现的输入内容。
例如:
用户输入:
3
cat,dog,good-luck
1,2,5
do not use,that
则程序输出:(word文档中可能不整齐,拷贝到记事本中看)
±———±–±——–+
|cat |dog|good-luck|
±———±–±——–+
|1 |2 |5 |
±———±–±——–+
|do not use| |that |
±———±–±——–+
从中不难看出:
两个连续的逗号表示中间有一个内容为空的单元
列的数目由最大的单元数的那行决定
列的宽度由同列的最宽的单元决定
单元格中的信息左对齐

可以假设:用户输入的最大行数为30,可能的最多列数为40。
*/
import java.util.Scanner;
public class 画表格 {
// 输出
public static void show(String[][] s,int[] len){
StringBuffer sb = new StringBuffer(“+”);
for(int i=0;i<len.length;i++){
for(int j=0;j<len[i];j++){
sb.append(“-”);
}
sb.append(“+”);
}
System.out.println(sb);
for(String[] x:s){
for(String y:x){
System.out.print(y);
}
System.out.println(“\n”+sb);
}
}
// 拆分串
public static String[][] splitS(String[] s){
String[][] t = new String[s.length][];
for(int i=0;i<s.length;i++){
t[i] = s[i].split(“,”); // 按分隔符拆分
}
return t;
}
// 取得长一个数组长度
public static int maxArrLen(String[] s){
String[][] t = splitS(s);
int maxL = 0;
for(String[] x:t){
for(String y:x){
if(y.length()>maxL){
maxL = x.length;
}
}
}
return maxL;
}
// 得到拆分处理后果的数组
public static String[][] getArr(String[] s,int n){
String[][] ss = new String[n][maxArrLen(s)]; // 拆分串
String[][] t = splitS(s); // 得到临时数组t用来给ss赋值
for(int i=0;i<ss.length;i++){ // 给ss赋值
for(int j=0;j<ss[i].length;j++){
if(j<t[i].length){
ss[i][j] = t[i][j]; // 赋值
}else{
ss[i][j] = “”; // 列数不够,则添空格
}
}
}
return ss;
}
// 得到每列的最长的串的长度
public static void maxLen(String[][] t, int[] len) {
for(int i=0;i<len.length;i++){
for(int j=0;j<t.length;j++){
if(i<t[j].length&&t[j][i].length()>len[i]){
len[i] = t[j][i].length(); // 得到每列的最长的串的长度
}
}
}
}
// 填充 “|” 和 ” ”
public static String fillS(String s,int n,int j,int end){
StringBuffer sb = new StringBuffer();
int x = n-s.length();
sb.insert(0, ‘|’);
sb.append(s);
for(int i=0;i<x;i++){
sb.append(” “);
}
if(j==end){
sb.append(”|“);
}
return sb.toString();
}
// 补空格和”|“操作
public static void fillSpace(String[][] data,int[] len){
for(int i=0;i<data.length;i++){
for(int j=0;j<data[i].length;j++){
if(data[i][j].length()<=len[j]){
data[i][j] = fillS(data[i][j],len[j],j,data[i].length-1); // 补空格
}
}
}
}
public static void f(String[] s,int n){
String[][] data = getArr(s,n); // 得到拆分后的所有数据
int[] len = new int[data[0].length]; // 每列最大宽度
maxLen(data, len); // 为len赋值(每列宽度)
fillSpace(data,len); // 补空格 加”|”
show(data,len); // 输出
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
Scanner scan2 = new Scanner(System.in);
System.out.println(“输入的行数(整数)”);
int n = scan.nextInt();
String[] s = new String[n];
for(int i=0;i<n;i++){
s[i] = scan2.nextLine();
}
f(s,n);
}
}

运行结果:
输入的行数(整数)
3
cat,dog,good-luck
1,2,5
do not use,that
±———±–±——–+
|cat |dog|good-luck|
±———±–±——–+
|1 |2 |5 |
±———±–±——–+
|do not use| |that |
±———±–±——–+

94.人民币金额大写

/*
在与财务相关的应用中,经常会用到人民币金额的大写,比如发票的打印程序。
本题的任务是:从键盘输入一个十亿以内的正整数(int类型),把它转换为人民币金额大写(不考虑用户输入错误的情况)。
比如,用户输入:35201,程序输出:叁万伍仟贰佰零壹
用户输入:30201,程序输出:叁万零贰佰零壹
用户输入:30001,程序输出:叁万零壹
用户输入:31000,程序输出:叁万壹仟
用户输入:120023201,程序输出:壹亿贰仟零贰万叁仟贰佰零壹
用户输入:120020001,程序输出:壹亿贰仟零贰万零壹
用户输入:100000001,程序输出:壹亿零壹
可以看到,在万后满千位,则不加零,否则要补零,但不要出现类似“零零”的情况。
在亿后满千万位,则不加零,否则要补零,但整个“万档”没有数字时,“万”字省去。
*/
import java.util.Scanner;

public class 人民币金额大写 {
static char[] uper = {‘零’,‘壹’,‘贰’,‘叁’,‘肆’,‘伍’,‘陆’,‘柒’,‘捌’,‘玖’}; // 大写数字
static char[] unit = {’ ‘,‘拾’,‘佰’,‘仟’,‘万’,‘拾’,‘佰’,‘仟’,‘亿’,‘拾’,‘佰’}; // 单位
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入一个十亿以内的正整数(int类型)”);
String s = scan.nextLine();
StringBuffer sb = new StringBuffer();
int num0 = 0; // 记录连续的零的个数
for(int i=s.length()-1;i>=0;i–){
if(s.charAt(i)!=‘0’){
sb.insert(0,unit[s.length()-1-i]);
}
if(s.length()-1-i4){
sb.insert(0,‘万’);
}
if(s.charAt(i)
‘0’){
num0++; // 统计零的个数
}else{
num0 = 0;
}
if(num0<=1){ // 添加大字数字
sb.insert(0,uper[s.charAt(i)-‘0’]);
}
}
if(sb.charAt(sb.length()-1)==‘零’){ // 去掉最后的”零”
sb.deleteCharAt(sb.length()-1);
}
String ss = sb.toString();
ss = ss.replace(“零万”, “万”);
ss = ss.replace(“亿万”, “亿”);
ss = ss.replace(“万万”, “万”);
System.out.println(ss);
}
}

运行结果:
输入一个十亿以内的正整数(int类型)
120023201
壹亿贰仟零贰万叁仟贰佰零壹

95.罗马数字转十进制

古罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候, 
现在看起来简直不能忍受,所以在现代很少使用了。之所以这样,不是因为发明表示法的人的智力的问题, 
而是因为一个宗教的原因,当时的宗教禁止在数字中出现0的概念! 
罗马数字的表示主要依赖以下几个基本符号: 
I  1 
V  5 
X  10 
L  50 
C  100 
D  500 
M  1000 
这里,我们只介绍一下1000以内的数字的表示法。 
单个符号重复多少次,就表示多少倍。最多重复3次。 
    比如:CCC表示300  XX表示20,    但150并不用LLL表示,这个规则仅适用于I X C M。 
如果相邻级别的大单位在右,小单位在左,表示大单位中扣除小单位。 
    比如:IX表示9  IV表示4  XL表示40 更多的示例参见下表,你找到规律了吗?

I,1
II,2
III,3
IV,4
V,5
VI,6
VII,7
VIII,8
IX,9

X,10
XI,11
XII,12
XIII,13
XIV,14
XV,15
XVI,16
XVII,17
XVIII,18
XIX,19
XX,20
XXI,21
XXII,22
XXIX,29
XXX,30
XXXIV,34
XXXV,35
XXXIX,39
XL,40
L,50
LI,51
LV,55
LX,60
LXV,65
LXXX,80
XC,90
XCIII,93
XCV,95
XCVIII,98
XCIX,99

C,100
CC,200
CCC,300
CD,400
D,500
DC,600
DCC,700
DCCC,800
CM,900
CMXCIX,999
本题目的要求是:请编写程序,由用户输入若干个罗马数字串,程序输出对应的十进制表示。
输入格式是:第一行是整数n,表示接下来有n个罗马数字(n<100)。
以后每行一个罗马数字。 罗马数字大小不超过999。
要求程序输出n行,就是罗马数字对应的十进制数据。
例如,用户输入:
3
LXXX
XCIII
DCCII
则程序应该输出:
80
93
702
注意:
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。
*/
import java.util.Scanner;

public class 罗马数字转十进制 {
public static int getNum(char c){
switch©{
case ‘I’: return 1;
case ‘V’: return 5;
case ‘X’: return 10;
case ‘L’: return 50;
case ‘C’: return 100;
case ‘D’: return 500;
case ‘M’: return 1000;
}
return 0;
}
public static int format(String s){
int sum = 0; // 总和
for(int i=0;i<s.length();i++){
int a,b; // 取得两个相邻的两个值
a = getNum(s.charAt(i));
if(i+1<s.length()){
b = getNum(s.charAt(i+1));
}else{
b = 0;
}
if(a<b){ // 对比两个值
sum += b-a; // 前小后大时,sum=大-小
i++; // 这里的i++和(for里的i++) i 会后移两位 ,再次进行
}else{
// 前大后小,或者相等时, sum = 前大元素 , 上边的(for里的i++) i 会后移一位
sum += a;
}
}
return sum;
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入整数n,表示接下来有n个罗马数字(n<100)”);
int n = scan.nextInt();
String[] s = new String[n];
scan.nextLine();
for(int i=0;i<n;i++){ // 输入数据
s[i] = scan.nextLine();
}
for(int i=0;i<s.length;i++){ // 格式化并输出
System.out.println(format(s[i]));
}
}
}

方法二:(用Map添加对应数字)
import java.util.Scanner;
import java.util.HashMap;

public class 罗马数字转十进制2 {
@SuppressWarnings(“serial”)
static HashMap<Character,Integer> Map =
new HashMap<Character,Integer>(){
{
put(‘I’,1);
put(‘V’,5);
put(‘X’,10);
put(‘L’,50);
put(‘C’,100);
put(‘D’,500);
put(‘M’,1000);
}
};
public static int format(String s){
int sum = 0; // 总和
int i=0;
while(i<s.length()){
int a = Map.get(s.charAt(i));
int b ;
if(i+1<s.length()){
b = Map.get(s.charAt(i+1));
}else{
b = 0;
}
if(a<b){
sum += b – a;
i += 2;
}else{
sum += a;
i++;
}
}
return sum;
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入整数n,表示接下来有n个罗马数字(n<100)”);
int n = scan.nextInt();
String[] s = new String[n];
scan.nextLine();
for(int i=0;i<n;i++){ // 输入数据
s[i] = scan.nextLine();
}
for(int i=0;i<s.length;i++){ // 格式化并输出
System.out.println(format(s[i]));
}
}
}

运行结果:
输入整数n,表示接下来有n个罗马数字(n<100)
3
LXXX
XCIII
DCCII
80
93
702

96.三角螺旋阵

方阵的主对角线之上称为“上三角”。
请你设计一个用于填充n阶方阵的上三角区域的程序。填充的规则是:使用1,2,3….的自然数列,从左上角开始,按照顺时针方向螺旋填充。
例如:当n=3时,输出:
1 2 3
6 4
5
当n=4时,输出:
1 2 3 4
9 10 5
8 6
7
当n=5时,输出:
1 2 3 4 5
12 13 14 6
11 15 7
10 8
9
程序运行时,从标准输入获得整数n(3~20)
程序输出:方阵的上三角部分。
要求格式:每个数据宽度为4,右对齐。

*/
import java.util.Scanner;

public class 三角螺旋阵 {
// 输出
public static void print(int[][] m){
for(int[] x:m){
for(int y:x){
System.out.printf(“%4d”,y);
}
System.out.println();
}
}
// 初始化
public static void init(int[][] m){
for(int i=0;i<m.length;i++){
m[i] = new int[m.length-i];
}
}
// 螺旋填充数字
public static void f(int[][] m,int k,int num){
if(k>=m.length/2) return ;
// 第一行
for(int i=k;i<m[k].length-k;i++){
m[k][i] = num++;
}
// 最后一位
for(int i=k+1;i<m[k].length-k;i++){
m[i][m[i].length-1-k] = num++;
}
// 左列
for(int i=m[k].length-2-k;i>k;i–){
m[i][k] = num++;
}
f(m,k+1,num); // 递归进行内圈填充
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println(“输入整数n(3~20)”);
int n = scan.nextInt();
int[][] m = new int[n][];
init(m); // 初始化
f(m,0,1); // 螺旋填充数字
print(m); // 输出
}
}

运行结果:
输入整数n(3~20)
5
1 2 3 4 5
12 13 14 6
11 15 7
10 8
9

97.提取拼音首字母

在很多软件中,输入拼音的首写字母就可以快速定位到某个词条。
比如,在铁路售票软件中,输入: “bj”就可以定位到“北京”。
怎样在自己的软件中实现这个功能呢?问题的关键在于:对每个汉字必须能计算出它的拼音首字母。

GB2312汉字编码方式中,一级汉字的3755个是按照拼音顺序排列的。
我们可以利用这个特征,对常用汉字求拼音首字母。

GB2312编码方案对每个汉字采用两个字节表示。第一个字节为区号,第二个字节为区中的偏移号。
为了能与已有的ASCII编码兼容(中西文混排),区号和偏移编号都从0xA1开始。

我们只要找到拼音a,b,c,…x,y,z 每个字母所对应的GB2312编码的第一个汉字,
就可以定位所有一级汉字的拼音首字母了(不考虑多音字的情况)。
下面这个表给出了前述信息。请你利用该表编写程序,求出常用汉字的拼音首字母。
a 啊 B0A1
b 芭 B0C5
c 擦 B2C1
d 搭 B4EE
e 蛾 B6EA
f 发 B7A2
g 噶 B8C1
h 哈 B9FE
j 击 BBF7
k 喀 BFA6
l 垃 C0AC
m 妈 C2E8
n 拿 C4C3
o 哦 C5B6
p 啪 C5BE
q 期 C6DA
【输入、输出格式要求】
用户先输入一个整数n (n<100),表示接下来将有n行文本。接着输入n行中文串(每个串不超过50个汉字)。
程序则输出n行,每行内容为用户输入的对应行的汉字的拼音首字母。
字母间不留空格,全部使用大写字母。
例如:
用户输入:
3
大家爱科学
北京天安门广场
软件大赛
则程序输出:
DJAKX
BJTAMGC
RJDS
*/
import java.util.Scanner;
public class 提取拼音首字母{
static char[] ch = { ‘啊’, ‘芭’, ‘擦’, ‘搭’, ‘蛾’, ‘发’, ‘噶’,
‘哈’, ‘击’, ‘喀’, ‘垃’, ‘妈’, ‘拿’, ‘哦’, ‘啪’, ‘期’, ‘然’, ‘撒’,
‘塌’, ‘挖’, ‘昔’, ‘压’, ‘匝’, };
static char[] CX = { ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’,
‘H’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’, ‘Q’, ‘R’, ‘S’,
‘T’, ‘W’, ‘X’, ‘Y’, ‘Z’, };
static int[] cn = new int[ch.length];
static{ // 初始化汉字变为十进制
for(int i=0;i<cn.length;i++){
cn[i] = getNum(ch[i]);
}
}
// 将一个汉字(GB2312)转换为十进制表示
public static int getNum(char c){
byte[] b = null;
try {
b = (“”+c).getBytes(“GB2312”);
} catch (Exception e) {
e.printStackTrace();
} // 汉字变为十进制(核心)
return (b[0]<<8&0xff00) + (b[1]&0xff);
}
// 返回汉字的首字母
public static char firstC(char c){
int n = getNum©;
for(int i=0;i<cn.length-1;i++){
if(n>=cn[i]&&n<cn[i+1]){
return CX[i];
}
}
return ‘Z’;
}