蒟蒻一枚,写此篇博客作为我的赛前突击,基本每年后面的两个大题或者是很难的题我都没有做,我的目标是能混省二我就谢天谢地了~~
此类题目主要是考察对时间的操作,主要用到的API是LocalDate,LocalTime,Calendar
,关于对时间的操作很容易考,所以一定掌握这几个类。
此题就是暴力破,五重for循环,注意一下限制条件就可以了
一看题目就可以知道这是一道搜索的题目,所以我们首先考虑深搜和广搜
public class Main {
public static void main(String[] args) {
int m = dfs(0, 0);
System.out.println(m);
}
// dfs
public static int dfs(int i, int j) {
if (i == 3 || j == 4) {
return 1;
}
return dfs(i + 1, j) + dfs(i, j + 1);
}
}
根据找规律我们可以发现这是考察斐波那契数列,某个相邻两项的比值。
关于求解斐波那契数列的问题由于它的后期数很大,所以我们用API进行大数操作,我们就知道要用BigInteger
和BigDecimal
来做。
public class Main {
public static void main(String[] args) {
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
for (int i = 3; i < 500; i++) {
BigInteger t = b;
b = a.add(b);
a = t;
}
BigDecimal div = new BigDecimal(a, 110).divide(new BigDecimal(b, 110), BigDecimal.ROUND_HALF_DOWN);
System.out.println(div.toPlainString().substring(0, 103));
}
}
填空题,考察面向对象,暴力试皆可
填空题,快排的变种,暴力试即可
枚举,注意输入的时候需要吃掉一个换行符input.nextline()
日后有缘再续
日后有缘再续
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = sc.nextInt();
}
sc.close();
int ans = 0;
for (int i = 0; i < arr.length; i++) {
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int j = i; j < arr.length; j++) {
max = Math.max(max, arr[j]);
min = Math.min(min, arr[j]);
if ((max - min + 1) == j - i + 1) {
ans++;
}
}
}
System.out.println(ans);
}
}
思维题,不需要编程,读懂题意,直接动手画就可以了
规律思维题,找规律,1+2的n次方
public class Main {
public static void main(String[] args) {
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);
}
}
// System.out.println(Arrays.toString(arr));
int len = 2014;
while (len != 1) {
int mm = 0;
for (int i = 1; i < len; i += 2) {
arr[mm++] = arr[i];
}
len = mm;
}
System.out.println(arr[0]);
}
}
老师异常激动的说这简直就是水题,太简单了,求偶数项,so,确实水,我都会,hhh
填空题,答案:4/(n-1)
,过~
关键思路在于枚举四个数并且求两个数的最大公约数,求公约数是关键
//递归求解最大公约数
public static int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
全排列,递归框架,然后check求解,求解全排列用递归
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
char[] a = {
'A', 'A', '2', '2', '3', '3', '4', '4' };
fun(a, 0);
for (String c : set) {
System.out.println(c);
}
}
// 去重
static Set<String> set = new HashSet<>();
// 递归框架求解全排列
public static void fun(char[] a, int k) {
// 判断
if (k == a.length) {
String s = new String(a);
if (check(s)) {
set.add(s);
}
}
// 全排列
for (int i = k; i < a.length; i++) {
char t = a[k];
a[k] = a[i];
a[i] = t;
fun(a, k + 1);
// 回溯
t = a[k];
a[k] = a[i];
a[i] = t;
}
}
// 检查
public static boolean check(String s) {
if (s.lastIndexOf('A') - s.indexOf('A') == 2 && s.lastIndexOf('2') - s.indexOf('2') == 3
&& s.lastIndexOf('3') - s.indexOf('3') == 4 && s.lastIndexOf('4') - s.indexOf('4') == 5) {
return true;
} else {
return false;
}
}
}
模拟题,根据情况仔细模拟就可以了,核心思路就是一个圈,用数组表示,先减去一半,然后再把后面的一半加到前面的数上面,最后一个数是将首尾的一半加上。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();// 输入几个孩子
// 用数组表示一个圈
int[] a = new int[n];
for (int i = 0; i < a.length; i++) {
a[i] = input.nextInt();
}
int ans = 0;
while (true) {
int t = a[0];
for (int i = 0; i <= n - 2; i++) {
a[i] -= a[i] / 2;// 先减去一半 再加上下一项的一半
a[i] += a[i + 1] / 2;
if ((a[i] & 1) == 1) {
ans++;
a[i]++;
}
}
// 最后一项也要进行一样的操作
a[n - 1] -= a[n - 1] / 2;
a[n - 1] += t / 2;
if ((a[n - 1] & 1) == 1) {
ans++;
a[n - 1]++;
}
// 检验
if (check(a, n)) {
System.out.println(ans);
break;
}
}
}
// 检验
public static boolean check(int[] a, int n) {
int t = a[0];
for (int i = 1; i < n; i++) {
if (a[i] != t) {
return false;
}
}
return true;
}
}
记忆型递归
emmmm。。。。。。
这。。。小学就学过的题目,水题。。。过了过了
暴力破,只需要知道范围就可以了,我们可以用计算机求得左区间肯定是小于99,因为当99的立方是个很大的数,不可能相加等于99
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int count = 0;
for (int i = 1; i < 99; i++) {
int m = i * i * i;
String s = String.valueOf(m);
int sum = 0;
for (int j = 0; j < s.length(); j++) {
int a = Integer.parseInt(String.valueOf(s.charAt(j)));
sum += a;
}
if (sum == i) {
count++;
}
}
System.out.println(count);
}
}
解法一:暴力破,超级多重for循环,但是很容易晕。。。
第二种解法是用数学思维,根据进位的变化来推出某些数,然后再用循环来求解这样的循环就会简便的多
老师说这题很难,当时难倒过众好汉,难在特例很难给出,v.size()-v.indexOf(n)
九个数组组成一个分数,此题考查全排列递归框架,然后递归多分支探索,之后我们需要回溯,所以我们只需要填写回溯部分就可以了,回溯部分就是我们递归之前的语句。
//全排列的实现算法 递归+交换
package Test.Arithmetic;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
perm(new int[] {
1, 2, 3, 4 }, 0, 3);
}
// 递归输出全排列
public static void perm(int[] array, int start, int end) {
if (start == end) {
System.out.println(Arrays.toString(array));
} else {
for (int i = start; i <= end; i++) {
swap(array, start, i);
perm(array, start + 1, end);
swap(array, start, i);
}
}
}
// 交换数字
public static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
此题很有意思,此年的一些题目都是一些很新奇的解决方案,比如这道题目,解题思路就很新颖,一开始我看了一会没有思路,听老师一讲,醍醐灌顶,老师说有两个方法,方法一就是比较普通的办法,等差数列,比较麻烦。ps:我连这个都没想到。然后第二个方法比较新奇,就是因为是只改变了两个部分,所以我们用新的减去旧的再把这两个加起来,肯定等于最后的结果相减。
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 46; i++) {
for (int j = i + 2; j <= 48; j++) {
if (i * (i + 1) - (i + i + 1) + j * (j + 1) - (j + j + 1) == 2015 - 1225) {
System.out.println(i + " " + j);
}
}
}
}
}
思维题,思维上有点难,,emmm,先过,日后有缘再续
老师说是水题,但我却没想到,,ctml。。。我真愚蠢,我真笨,我真是蒟蒻!!!
思维题,这道题目老师说很简单,但是我却想麻烦了,我居然还蠢到去用递归来解决,结果溢出找错找了半天,最后无果而终,nnp,其实这道题目的思维很简单,用迭代就可以实现,就那几个点拿捏好了就可以了,第一个是你每消耗三瓶就会产生一瓶,所以你其实是从总的瓶数里面减去了两瓶,然后我们拿一个ans来计数,初始值为零,每次都加上三个瓶数,因为每次都是消耗三个,并且前面消耗了三个产生了一个新的,所以每次并不会多加,循环的条件就是瓶数大于等于三,最后将不到三瓶的数目加给ans。
代码实现
public class Main {
public static void main(String[] args) {
int ans = 0;
int n=100;
while(n >= 3) {
n -= 2;
ans += 3;
}
ans += n;
System.out.println(ans);
}
}
dp,矩阵,,,太难了。。。。
。。。。。
规律题,静下心来找规律就可以了,千万不要想的太难
public class Main {
public static void main(String[] args) {
for (int i = 1; i < 100; i++) {
int t = i * (i - 1) / 2;
if ((236 - t) % i == 0) {
System.out.println((236 - t) / i);
}
}
}
}//总感觉是似曾相识啊!!!
又是全排列,固定套路,递归,回溯即可
填空题,过了,
填空题。。。递归
提交结果题,全排列
难题开始,
枚举优化(hash缓存)
日后有缘再续
hash查找+标注+区间树
ps:这一年的题居然考了三道全排列,但感觉16年的题目普遍偏难,当年要是我考的话可能连省三都没有。。。
不用编程,思维题,用Excel表格做,水题
全排列问题,
import static java.lang.Math.*;
/**
* 全排列模板
*/
public class Main {
static int[] a = {
1, 2, 3, 4, 5, 6, 7, 8, 9 };
static int ans = 0;
public static void main(String[] args) {
fun(0);
System.out.println(ans / 6);
}
// 全排列函数
public static void fun(int k) {
// 先判断是否到达边界 check的逻辑可能不同,别的相同
if (k == a.length) {
int x1 = a[0] + a[1] + a[3] + a[5];
int x2 = a[0] + a[2] + a[4] + a[8];
int x3 = a[5] + a[6] + a[7] + a[8];
if (x1 == x2 && x2 == x3) {
ans++;
}
}
// 然后进行全排列
for (int i = k; i < a.length; i++) {
{
int t = a[i];
a[i] = a[k];
a[k] = t;
}
fun(k + 1);
// 回溯
{
int t = a[i];
a[i] = a[k];
a[k] = t;
}
}
}
}
这道题目的思路就是从第一行开始遍历到最后一行,每一行遍历都将这个的值分给下一行的相同位置和此位置的下一个位置,最后对最后一行进行排序验证最小值是不是题目要求给的那个,由此输出最大值。但是值得要注意的是我们题目给定的最大值,无论如何都无法加到这个值,所以我们将输入的值乘以2的30次方来计算,最后得到的肯定是结果的倍数,约分就可以了。
老师一上来就说这道题目不想讲,说代码量太大。。。我:无语~~
170多行代码,,,过了
此题不难,题意简单明了,就是让你取出一个整形数字的第n位,填空题,是用递归实现的,return f(x/10,k);
。x肯定是变小的,所以除以10,k不变
用DP来求,用一个二维数组来存放两个字符串,行列相等即上一个位置加一,a[i][j] = a[i-1][j-1] + 1;
根据条件模拟即可,有点麻烦,需要判断的条件很多,注意细节
背包问题,有点难,不会。。。
考察枚举优化,此题用迭代暴力的话肯定会爆,所以用二分优化就可以了,这道题目比上一题简单很多
太麻烦,,没时间看了
水题
圆的基本方程
双重for循环,四个象限,先只看第一象限,即i*i + j*j <= 1000*1000
,满足这个条件的加一,最后将这个结果乘以4就可以了。
大数运算,BigInteger和BigDecimal
后补
三层循环暴力破
后补
。。。。。剩下的部分日后有缘再续上吧~~明天加油!!!