A 猜年龄
小明带两个妹妹参加元宵灯会。别人问她们多大了,她们调皮地说:“我们俩的年龄之积是年龄之和的6倍”。小明又补充说:“她们可不是双胞胎,年龄差肯定也不超过8岁啊。”
请你写出:小明的较小的妹妹的年龄。
解析:对于年龄来说普遍定义不超过100,所以在采用循环的时候,界限最大到100即可。
使用两个for循环来分别来表示两个妹妹的年龄,外层循环表示较小的妹妹的年龄,内层循环表示较大的妹妹的年龄。根据题目 年龄之积为年龄之和的6倍,年龄之差不超过8岁得出判断条件公司为 i * j == 6 * (i + j) && i < j 可输出所有组合情况 加上 j - i <= 8 de 条件可输出唯一解。
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 1; i < 100; i++) {//较小的年龄
for (int j = i; j < 100; j++) {//较大的年龄
// if (i*j==6*(i+j) && i<j) {
// System.out.println(i+" "+j);
// }
if (i*j==6*(i+j) && i<j && j-i<=8) {
System.out.println(i+" "+j);
}
}
}
}
}
B 等额本金
小明从银行贷款3万元。约定分24个月,以等额本金方式还款。这种还款方式就是把贷款额度等分到24个月。每个月除了要还固定的本金外,还要还贷款余额在一个月中产生的利息。
假设月利率是:0.005,即:千分之五。那么,
第一个月,小明要还本金 1250, 还要还利息:30000 * 0.005,总计 1400
第二个月,本金仍然要还 1250, 但利息为:(30000-1250) * 0.005 总计 1393.75请问:小明在第15个月,应该还款多少(本金和利息的总和)?
解析:根据题目可得出 还款金额 = 本金 + 利息
利息 = (总贷款金额 - 本金) * 0.005 但 第一次还款利息 = 总贷款金额 * 0.005
程序设计:直接定义总贷款金额 n = 30000 在15次循环中 先输出还款金额 ,n 再减去1250,最后一次输出为15月还款金额。
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=30000; //本金
for (int i = 0; i < 15; i++) {
System.out.println(1250+n*0.005); //还款
n-=1250; //本金每次还款减1250
}
}
C 猜字母
把abcd...s共19个字母组成的序列重复拼接106次,得到长度为2014的串。
接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字母。
得到的新串再进行删除奇数位置字母的动作。如此下去,最后只剩下一个字母,请写出该字母。
解析:由题意把a~s序列拼接106次,直接定义字符串 s = "abcdefghijklmnopqrs" 使用for循环进行106次拼接。
1.使用递归进行删除奇数位置的字母,递归结束条件为字符串长度为1。
在递归中 定义一个新的字符串s 用来存储删除奇数位置后的新字符串 用一个for循环来进行删除操作,由于奇数位置的下标为偶数,所以在判断的时候 i % 2==0 为要删除的奇数位置字母,将该字母存入字符串后,将字符串置为空;i % 2 != 0的存入定义的新字符串s;
由于存入的字母为字符格式,获取字符串中单个字符使用 charAt(i)
转化字符串 String.valueOf()。
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="abcdefghijklmnopqrs";
String s1="";
for (int i = 0; i < 106; i++) {
s1+=s;
}
System.out.print(s1);
System.out.println();
System.out.println(sub(s1));
}
private static String sub(String s1) {
// TODO Auto-generated method stub
if (s1.length()==1) {
return s1;
}
String s="";
//在s1的长度下循环
for (int i = 0; i < s1.length(); i++) {
if (i%2==0) {//如果为偶数位
//转换为字符存入ss
String ss=String.valueOf(s1.charAt(i));
//让ss为空
ss="";
}else {
s+=String.valueOf(s1.charAt(i));
}
}
return sub(s);
}
}
2.使用while循环进行删除奇数位置的字母,循环结束条件为字符串长度为1。
首先 定义一个大小为2014的数组,利用表达式 (char)('a'+j) 生成字母序列;
定义 序列长度 len = 2014 ,当 len != 1时进入while循环;在循环体内利用一个新数组进行存储要保留的字母,循环增量为2;最后将新数组的长度赋值给len。
注:因为奇数位置的字母下标为偶数位,所以for循环的初始为1,跳过奇数位置的位置,循环增量为2。
public static void main(String[] args) {
// TODO Auto-generated method stub
char arr[]=new char[2014];
int index=0;//数组下标
for (int i = 0; i < 106; i++) {
for (int j = 0; j < 19; j++) {
arr[index++]=(char)('a'+j);
}
}
for (char c : arr) {
System.out.print(c);
}
System.out.println();
int len=2014;
while (len!=1) {
int k=0;
//拿走奇数位的字母 保留偶数位的字母
for (int i = 1; i < len; i+=2) {
arr[k++]=arr[i];
}
len=k; //剩下的数组长度
}
System.out.println(arr[0]);
}
D 大衍数列
中国古代文献中,曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。
它的前几项是:0、2、4、8、12、18、24、32、40、50 ...
其规律是:对偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。
以下的代码打印出了大衍数列的前 100 项。
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 1; i < 100; i++) {
if (i%2==0) {//填空
System.out.println((i*i)/2);
}else {
System.out.println((i*i-1)/2);
}
}
}
}
E 写日志
写日志是程序的常见任务。现在要求在 t1.log, t2.log, t3.log 三个文件间轮流写入日志。也就是说第一次写入t1.log,第二次写入t2.log,... 第四次仍然写入t1.log,如此反复。
下面的代码模拟了这种轮流写入不同日志文件的逻辑。
解析:由题意可知三个日志为一次循环,由给定代码可知 先定义了日志文件名,所以在输出第二个日志时,需要对 n 加 1,到第四个日志文件时需回到 n 为1,即填空处为 n = n % 3 + 1 或 n = (++n) % 4 == 0?1:n
n = n % 3 + 1 是对 n 后进行自增1,所以循环基数为3
n = (++n) % 4 == 0?1:n 是对n先进行自增1,所以循环基数为4
public class Main {
private static int n=1;
public static void write(String msg) {
String filename = "t"+n+".long";
//n=(++n)%4==0?1:n;
n=n%3+1;//填空
System.out.println("write to file:"+filename+" "+msg);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Main4 man=new Main4();
man.write("msg");
man.write("msg");
man.write("msg");
man.write("msg");
man.write("msg");
}
}
F 李白打酒
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
解析:此题使用递归。由于最后一次遇到的是花,且正好把酒喝完,所以递归传值为店--5,花--9,酒--2;递归结束条件为 店--0,花--0,酒--1。
进行两种情况:
逢店加一倍:递归传值为 店-1,花不变,酒*2
遇花喝一斗:递归传值为 店不变,花-1,酒-1
public class Main {
static int k;
public static void main(String[] args) {
// TODO Auto-generated method stub
f(5,9,2);
System.out.println(k);
}
private static void f(int dian, int hua, int jiu) {
// TODO Auto-generated method stub
if(dian==0 && hua==0 && jiu==1)
k++;
// 逢店 店-1 酒加倍
if(dian>0) f(dian-1,hua,jiu*2);
// 遇花 花-1 酒-1
if(hua>0) f(dian,hua-1,jiu-1);
}
}
G 奇怪的分式
上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:
1/4 乘以 8/5
小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图)
老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!
对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢?
请写出所有不同算式的个数(包括题中举例的)。
显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。
但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!
解析:要满足题意,这里解题的时候使用了暴力破解,直接四个for循环,再结合题目,分子分母不能相同,在第二、三、四层for循环进行判断,下面的代码为四个数字都不相同,若只需要两个分式的分子分母不同,而不需要四个数字都不同,即在第二层和最后一层循环判断即可。
在循环体内部先进行正确的计算方式,然后对其结果进行计算最大公约数;然后再对两个方式用小明的计算方式进行拼接后,计算出最大公约数。判断正确计算的结果进行约分后 与 小明的新算法结果进行约分后 是否一致。
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int count=0;
for (int a = 1; a <=9; a++) {
for (int b = 1; b <=9; b++) {
if(a==b) continue;
for (int c = 1; c <=9; c++) {
if(c==a||c==b) continue;
for (int d = 1; d <=9; d++) {
if(d==a||d==b||d==c)continue;
// 正确计算的公约数
int x=gcd(a*c,b*d);
// 小明计算方式的公约数
int y=gcd(a*10+c,b*10+d);
// 对比两个计算结果约数后 是否一致
if ((a*c)/x==(a*10+c)/y && (b*d)/x==(b*10+d)/y) {
System.out.println(a+"/"+b+" "+c+"/"+d);
count++;
}
}
}
}
}
System.out.println(count);
}
// 最大公约数
private static int gcd(int a, int b) {
// TODO Auto-generated method stub
if(b==0) return a;
return gcd(b,a%b);
}
}