高斯日记、猜年龄、世纪末的星期、排他平方数、马虎的算式、振兴中华、组素数、第39级台阶

高斯日记

题目

大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如: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);//1799-07-16
	}

小结

  1. Calendar类创建实例:

    Calendar c = Calendar.getInstance();
    
  2. 调用set()赋值

  3. 调用getTime()获取Date对象

    • 这里有个细节,当使用get() 获取月份时,月份从0开始,还需要转换,这里转成Date对象,直接拿到正确规范的日期
  4. 日期格式化

     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
    
  5. 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;
	}

小结

  1. 该题借助HashSet不关心具体值,通过计算值个数完成验证
  2. 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;
			}
		}
	}

小结

  1. Calendar的月份不要设置成12,因为其从0计,故12月应该是11
  2. 要查阅API,得到Calendar.DAY_OF_WEEK对应的星期天的值是1

排他平方数

题目

小明正看着 203879 这个数字发呆。
原来,203879 * 203879 = 41566646641
这有什么神奇呢?仔细观察,203879 是个6位数,
并且它的每个数位上的数字都是不同的,
并且它平方后的所有数位上都不出现组成它自身的数字。
具有这样特点的6位数还有一个,请你找出它!
再归纳一下筛选要求:

  1. 6位正整数
  2. 每个数位上的数字不同
  3. 其平方数的每个数位不含原数字的任何组成数位

代码

	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);//639172
			}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();
	}

小结

  1. 数字比较大,用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);//142
	}

小结

  1. 无趣

振兴中华

题目

小明参加了学校的趣味运动会,其中的一个项目是:跳格子。
地上画着一些格子,每个格子里写一个字,如下所示:
从我做起振
我做起振兴
做起振兴中
起振兴中华
比赛时,先站在左上角的写着“从”字的格子里,
可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。
一直要跳到“华”字结束。
要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?

代码

	public void process() {
		System.out.println(jump(0, 0));//35
	}
	public int jump(int x,int y) {
		if(x == 4 || y == 3) {
			return 1;
		}
		return jump(x + 1, y) + jump(x, y + 1);
	}

小结

  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;
	}

小结

  1. 全排列,把每个元素都在某个位置放一遍,随着“确定”某一位置,再对剩余项全排列
    • 由此可知:处理逻辑相同,规模减少,存在终止条件(所有位置都排完),可以用递归
  2. 第二个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] 值,这样就重复了之前的一次操作,也即漏了一种情况
    • 所以如果没有第二个交换来保证原有顺序,便不能做到将每个值都放在某位置
  3. HashSet的意义在于去重

第39级台阶

题目

小明刚刚看完电影《第39级台阶》,离开电影院的时候,
他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。
先迈左脚,然后左右交替,最后一步是迈右脚,
也就是说一共要走偶数步。那么,上完39级台阶,
有多少种不同的上法呢?

代码

	private int count = 0;
	@Override
	public void process() {
		fun(39, false);
		System.out.println(count);//51167078
	}
	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++;
			}
		}
	}

小结

  1. 此题通过多加入一个参数,判断奇偶性(左右脚)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值