目录
题目链接:1.平方差 - 蓝桥云课 (lanqiao.cn)
思路
暴力偷分
发现规律
发现蹊跷
总结
题目链接:1.平方差 - 蓝桥云课 (lanqiao.cn)
思路
咱就是说,写蓝桥杯的题目的第一件事情是什么,那就是不管三七二十一先暴力一下把能拿到的分数拿到再说没毛病。
暴力偷分
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) throws IOException{
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
st.nextToken();
int L = (int) st.nval;
st.nextToken();
int R = (int) st.nval;
int res = 0;
for (int i = L; i <= R; i++) {
if (have(i)) {
res++;
}
}
System.out.println(res);
}
public static boolean have(int x) {
for (int i = 1; i <= x; i++) {
for (int j = 0; j < x; j++) {
if (x == i*i - j*j) {
return true;
}
}
}
return false;
}
}
嘿嘿
我不要脸!!~~~~~
发现规律
如果大家寻找一下数的规律
比如,1~16中满足题目要求的数字有
可以:1,3,4,5,7,8,9,11,12,13,15,16
不可以:2,6,10,14
满足要求的是奇数或者2的偶数倍
那么我就写下了如下的代码
// 1:无需package
// 2: 类名必须Main, 不可修改
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) throws IOException{
// 得出结论是,奇数和二的偶数倍都可以
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
st.nextToken();
int L = (int) st.nval;
st.nextToken();
int R = (int) st.nval;
int res = 0;
for (int i = L; i <= R; i++) {
// 遍历所有数看有那些数满足通过观察得到的规律
if (i % 2 != 0 || i % 4 == 0) {
res++;
}
}
System.out.println(res);
}
}
为什么,为什么只通过了90%,我的代码已经很完美了啊,啊啊啊啊啊啊啊,根本想不出来优化的方法了啊,难道我就要放弃了吗,放弃了吗,放弃了吗.........
发现蹊跷
我也是服了,你们知道为什么我这里的输入流一直使用的是StreamTokenizer吗,因为在输入的数据量比较大的情况下它的效率更高,可以提升速度,但是我真的是服啦!!!!!!!!记住前任的话,有利有弊,你得到了什么必然会失去什么。查了一下资料才知道这个小东西使用navl读取的数据默认都是double类型,如果我们long类型的长度已经超过了double类型的精度那么对不起,听天由命吧。所以我老老实实用回了Scanner万金油老哥┭┮﹏┭┮爱了。
package src;
//1:无需package
//2: 类名必须Main, 不可修改
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 得出结论是,奇数和二的偶数倍都可以
Scanner sc = new Scanner(System.in);
long L = sc.nextLong();
long R = sc.nextLong();
long res = 0L;
res += (R + 1)/2 - L/2;
res += R / 4 - (L - 1)/4;
System.out.println(res);
}
}
那么有些大聪明可能就不服了,写出了如下的处理方式
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
st.nextToken();
String lString = st.sval;
// 用于等一下的测试效果
System.out.println(lString);
long L = Long.parseLong(lString);
st.nextToken();
String rString = st.sval;
// 用于等一下的测试效果
System.out.println(rString);
long R = Long.parseLong(rString);
恭喜你,思路很棒,但是现实很骨感。。。。o(╥﹏╥)o
控制台是这样的
1 16
null
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Long.parseLong(Long.java:552)
at java.lang.Long.parseLong(Long.java:631)
at src.Main.main(Main.java:15)
为什么呢这里会是null呢wdf***?
因为默认情况下,StreamTokenizer将把数字解析为double类型,并将其值存储在nval
字段中。如果词素被认定为数字,sval
字段将为null。
所以这里就真的可以放弃StreamTokenizer,当然这个是可以修改处理方式的,但是有这时间不如直接换成Scanner更加爽
总结
累了,记住遇到这种类似数学的问题,先找规律,如果比较大的测试用例超时,优化代码,如果答案错误在代码逻辑没问题的情况下,看看精度问题。
下班!!!喽~~