高斯日记
题目
大数学家高斯有个好习惯:无论如何都要记日记。 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。 这或许也是个好习惯,它时时刻刻提醒着主人: 日子又过去一天,还有多少时光可以用于浪费呢? 高斯出生于:1777年4月30日。 在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。 高斯获得博士学位的那天日记上标着:8113 请你算出高斯获得博士学位的年月日。
代码
public void process() {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR,1777);
c.set(Calendar.MONTH,3);
c.set(Calendar.DAY_OF_MONTH,30);
System.out.println(c.getTime());
for (int i = 1; i < 8113; i++ ) {
c.add(Calendar.DAY_OF_YEAR,1);
}
Date d = c.getTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String s = simpleDateFormat.format(d);
System.out.println(s);
}
小结
-
Calendar类创建实例: Calendar c = Calendar.getInstance();
-
调用set() 赋值 -
调用getTime() 获取Date 对象
- 这里有个细节,当使用
get() 获取月份时,月份从0开始,还需要转换,这里转成Date对象,直接拿到正确规范的日期 -
日期格式化 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
-
for 循环小于等于的问题,可以试试题中的例子,验证出生当天算1还是0
猜年龄
题目
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。 他曾在1935~1936年应邀来中国清华大学讲学。 一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说: “我年龄的立方是个4位数。我年龄的4次方是个6位数。 这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。” 请你推算一下,他当时到底有多年轻。
代码
public void process() {
for (int i = 0; i < 100; i++) {
String f = i*i*i + "";
String s = i*i*i*i + "";
if(f.length() == 4 && s.length() == 6 && match(f + s)) {
System.out.println(i);
}
}
}
public boolean match(String s) {
Set<Character> set = new HashSet<Character>();
for(int i=0;i<s.length();i++){
set.add(s.charAt(i));
}
return set.size()==10;
}
小结
- 该题借助
HashSet 不关心具体值,通过计算值个数完成验证 - char的包装类:Character
世纪末的星期
题目
曾有邪教称1999年12月31日是世界末日。当然该谣言已经不攻自破。 还有人称今后的某个世纪末的12月31日,如果是星期一则会… 有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!! 于是,“谣言制造商”又修改为星期日… 1999年的12月31日是星期五,请问: 未来哪一个离我们最近的一个世纪末年(即xx99年) 的12月31日正好是星期天(即星期日)? 请回答该年份(只写这个4位整数,不要写12月31等多余信息)
代码
public void process() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, 11);
calendar.set(Calendar.DAY_OF_MONTH, 31);
for(int i = 2099;;i += 100) {
calendar.set(Calendar.YEAR, i);
if(calendar.get(Calendar.DAY_OF_WEEK) == 1) {
System.out.println(i);
break;
}
}
}
小结
- Calendar的月份不要设置成12,因为其从0计,故12月应该是11
- 要查阅API,得到
Calendar.DAY_OF_WEEK 对应的星期天的值是1
排他平方数
题目
小明正看着 203879 这个数字发呆。 原来,203879 * 203879 = 41566646641 这有什么神奇呢?仔细观察,203879 是个6位数, 并且它的每个数位上的数字都是不同的, 并且它平方后的所有数位上都不出现组成它自身的数字。 具有这样特点的6位数还有一个,请你找出它! 再归纳一下筛选要求:
- 6位正整数
- 每个数位上的数字不同
- 其平方数的每个数位不含原数字的任何组成数位
代码
public void process() {
Set<Character> set = new HashSet<>();
Set<Character> ad = new HashSet<>();
for(long n = 100000;n <= 999999;n++) {
String b = n + "";
if(getDistinct(b) != 6) {
continue;
}
String a = n*n + "";
for(int i = 0;i < b.length();i++) {
set.add(b.charAt(i));
}
for(int j = 0;j < a.length();j++) {
ad.add(a.charAt(j));
set.add(a.charAt(j));
}
if(set.size() == 6 + ad.size()) {
System.out.println(n);
}else {
ad.clear();
set.clear();
}
}
}
public int getDistinct(String str) {
Set<Character> set = new HashSet<>();
for(int i = 0;i < str.length();i++) {
char tmp = str.charAt(i);
if(tmp != '0') {
set.add(str.charAt(i));
}
}
return set.size();
}
小结
- 数字比较大,用int出错,故采用long即可
马虎的算式
题目
小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。 有一次,老师出的题目是: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 这样的算式一共有多少种呢?
代码
public void process() {
int count=0;
for(int a=1;a<=9;a++) {
for(int b=1;b<=9;b++) {
if(b==a)continue;
for(int c=1;c<=9;c++) {
if(c==b||c==a)continue;
for(int d=1;d<=9;d++) {
if(d==a||d==b||d==c)continue;
for(int e=1;e<=9;e++) {
if(e==a||e==b||e==c||e==d) continue;
if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e)){
count++;
}
}
}
}
}
}
System.out.println(count);
}
小结
- 无趣
振兴中华
题目
小明参加了学校的趣味运动会,其中的一个项目是:跳格子。 地上画着一些格子,每个格子里写一个字,如下所示: 从我做起振 我做起振兴 做起振兴中 起振兴中华 比赛时,先站在左上角的写着“从”字的格子里, 可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。 一直要跳到“华”字结束。 要求跳过的路线刚好构成“从我做起振兴中华”这句话。 请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
代码
public void process() {
System.out.println(jump(0, 0));
}
public int jump(int x,int y) {
if(x == 4 || y == 3) {
return 1;
}
return jump(x + 1, y) + jump(x, y + 1);
}
小结
- 递归求解,记忆此类代码形式
组素数
题目
素数就是不能再进行等分的数。比如:2 3 5 7 11 等。 9 = 3 * 3 说明它可以3等分,因而不是素数。 我们国家在1949年建国。如果只给你 1 9 4 9 这4个数字卡片, 可以随意摆放它们的先后顺序(但卡片不能倒着摆放啊,我们不是在脑筋急转弯!), 那么,你能组成多少个4位的素数呢? 比如:1949,4919 都符合要求。
代码
private Set<Integer> set = new HashSet<Integer>();
public void swap(int[] arr,int l ,int r) {
int t = arr[l];
arr[l] = arr[r];
arr[r] = t;
}
public void fun(int[] arr,int p) {
if(p == arr.length) {
int num = arr[0] * 1000 + arr[1] * 100 +arr[2] * 10 + arr[3];
if(isPrimeNumber(num)) set.add(num);
}
for(int i = p ; i < arr.length;i++) {
swap(arr, i, p);
fun(arr, p + 1);
swap(arr, i, p);
}
}
@Override
public void process() {
int[] arr = {1,9,4,9};
fun(arr, 0);
System.out.println(set.size());
}
public boolean isPrimeNumber(int n) {
if(n < 2) return false;
for(int i = 2; i < Math.sqrt(n);i++) {
if(n % i == 0) return false;
}
return true;
}
小结
- 全排列,把每个元素都在某个位置放一遍,随着“确定”某一位置,再对剩余项全排列
- 由此可知:处理逻辑相同,规模减少,存在终止条件(所有位置都排完),可以用递归
- 第二个swap的存在价值
- 对于 … a,b,c…序列,全排列时,计划依次将 t[a],t[b],t[c]放在a位置
- 而代码逻辑是每次取下一位进行替换,即t[a] 到 t[a],t[b] 到 t[a] ,t[c] 到t[a] …
- 如果没有第二个交换,考虑这样一种情况:
- 代码执行到该将t[c] 换到 t[a] 时,却可能由于原有顺序的打乱,现在t[c] 处存放的是原始序列t[a]的值,而不是原始序列t[c] 值,这样就重复了之前的一次操作,也即漏了一种情况
- 所以如果没有第二个交换来保证原有顺序,便不能做到将每个值都放在某位置
- HashSet的意义在于去重
第39级台阶
题目
小明刚刚看完电影《第39级台阶》,离开电影院的时候, 他数了数礼堂前的台阶数,恰好是39级! 站在台阶前,他突然又想着一个问题: 如果我每一步只能迈上1个或2个台阶。 先迈左脚,然后左右交替,最后一步是迈右脚, 也就是说一共要走偶数步。那么,上完39级台阶, 有多少种不同的上法呢?
代码
private int count = 0;
@Override
public void process() {
fun(39, false);
System.out.println(count);
}
public void fun(int n,boolean b) {
if(n > 2) {
fun(n - 1,!b);
fun(n - 2,!b);
}
if(n == 1 && b == true) count++;
if(n == 2) {
fun(1, !b);
if(b == true) {
count++;
}
}
}
小结
- 此题通过多加入一个参数,判断奇偶性(左右脚)
|