3月蓝桥集训第一周总结(Java解析)
1.数列求值
题目描述
运行限制
代码解析
这是我第一次接触快读,刚开始看的时候一脸懵,发现除了Scanner还有这样的方法读取。定义一个数组,第四项是前三项的和,这个很简单。
import java.io.*;
public class Main {
public static void main(String[] args)throws IOException {
StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter pw=new PrintWriter(new OutputStreamWriter(System.out));
int[] arr=new int[20190324];
arr[0]=1;arr[1]=1;arr[2]=1;
for(int i=3;i<arr.length;i++){
arr[i]=(arr[i-1]+arr[i-2]+arr[i-3])%10000;
}
pw.println(arr[20190323]);
pw.flush();
}
}
2.质数
题目描述
运行限制
代码解析
暴力搜索,从第四个质数搜索开始,用两层循环遍历每个可能的数。
import java.io.*;
public class Main {
public static void main(String[] args)throws IOException {
StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter pw=new PrintWriter(new OutputStreamWriter(System.out));
int sum=3;
for(int i=6;;i++){
int n=1;
for(int j=2;j<i;j++){
if(i%j==0){
n=0;
break;
}
}
if (n==1){
sum=sum+1;
}
if(sum==2019){
pw.println(i);
pw.close();
break;
}
}
}
}
3.饮料换购
题目描述
输入描述
输出描述
输入输出样例
运行限制
代码解析
给定一个循环条件:瓶盖>=3。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int num=scan.nextInt();
int res=num;
while(num>=3){
res+=num/3;
num=num/3+num%3;
}
System.out.println(res);
scan.close();
}
}
4.奇数倍数
题目描述
运行限制
代码解析
本题主要运用for,while循环,需要注意的是,用定义x=0在循环里面作为局部变量,在while循环里,当不符合条件时将x赋值为1,同时将该循环进行break,若满足条件,则j/10(对每一位数字进行筛选),当所有位数满足条件时,x仍然为0,则以x==0为条件在while循环外进行输出结果,记得重要的一点,对其进行return。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
int n=2019;
for(int i=1;;i+=2){
int j=i*n;
int x=0;
while(j!=0){
if(j%2==0){
x =1;
break;
}
j=j/10;
}
if(x==0){
System.out.println(i*n);
return;
}
}
}
}
5.求值
题目描述
运行限制
代码解析
本题运用枚举,需要注意应用Math.sqrt(),如果直接j运行的范围写成<=i,则运行结果超时,而对于应用Math.sqrt()方法,在最后对count约数进行统计时,需要对其进行×2,因为sqrt开平方,左边一侧有的,右边一侧也有。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
for(int i=6;;i++){
int count=0;
for(int j=1;j<=Math.sqrt(i);j++){
if(i%j==0){
count++;
}}
if(count*2==100){
System.out.println(i);
break;
}
}
}
}
6.求和
题目描述
输入格式
输出格式
评测用例
代码解析
本题相对难理解的是arr[i](sum-arr[i]);sum是对所有输入的数字进行相加,这样可以在arr[1]时直接sum,需要注意的是,其中它们两相乘时有一项乘arr[i]本身,所以这时我们需要减去arr[i]*arr[i]。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
long sum=0;
long result=0;
long []arr=new long[n];
for(int i=0;i<arr.length;i++){
arr[i]=sc.nextLong();
sum+=arr[i];
}
for(int i=0;i<arr.length;i++){
result+=arr[i]*(sum-arr[i]);
sum-=arr[i];
}
System.out.println(result);
sc.close();
}
}
7.数位排序
题目描述
输入格式
输出格式
样例说明
评测用例
代码解析
定义一个二维数组,一个用来存放原数据,一个存放数位和的数,后面用Arrays.sort(arr,((a,b)->{}))对数进行排序,这个方法适用于二维数组。排序好后直接输出一维的数。可以想象一下二维数组是两列n行,将第2列按要求排序好后就可以直接输出第一列的数即为答案。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int [][]arr=new int[n][2];
for(int i=0;i<n;i++){
arr[i][0]=i+1;
int t=arr[i][0];
int s=0;
while(t!=0){
s=s+t%10;
t/=10;
}
arr[i][1]=s;
}
Arrays.sort(arr,((a,b)->{
if(a[1]!=b[1]){
return a[1]-b[1];
}
return a[0]-b[0];
}));
System.out.println(arr[m-1][0]);
sc.close();
}
}
8.门牌制作
题目描述
运行限制
代码解析
注意for循环里面要将i赋值给num。将num作为判断条件,不能直接用i。注意求数位直接num/10
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
int sum=0;
for(int i=1;i<=2020;i++){
int num=i;
while(num!=0){
if(num%10==2){
sum++;
}
num /=10;
}
}
System.out.println(sum);
}
}
9.货物摆放
题目描述
答案提交
运行限制
代码解析
这道题我能想到用三个循环对其进行求方案,但是由于数据太大,以至于不能运行出来,借鉴了别人的想法,将n=2021041820210418进行开方求因子,这个让我学到了一个点,利用Math.sqrt(n)作为循环的限制条件,可以求出n其中的一个因子。而求出另外的一个因子,则需要另外定义一个m,用m=n/之前的一个因子(i),这时m就为n的另外一个因子,将所求的因子存放入到ArrayList数组中,最后利用该数组作为循环,能够很轻松的求出所有方案。整个程序需要注意的是不要用int定义,由于数据太大会超过int的范围。ArrayList数组和普通数组的区别。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
long n=2021041820210418l;
ArrayList<Long> arr=new ArrayList<>();
for(long i=1;i<=Math.sqrt(n);i++){
if(n%i==0){
arr.add(i);
long m=n/i;
if(m!=0){
arr.add(m);
}
}
}
int sum=0;
for(long i:arr){
for(long j:arr){
for(long k:arr){
if(i*j*k==n){
sum++;
}
}
}
}
System.out.println(sum);
}
}
10.跳跃
题目描述
输入描述
输出描述
输入输出样例
运行限制
代码解析
import java.util.Scanner;
public class Main {
static Scanner sr = new Scanner(System.in);
static int n = sr.nextInt();
static int m = sr.nextInt();
static int[][] map = new int[n][m];
static int dx[] = {0,0,0,1,2,3,1,2,1};
static int dy[] = {1,2,3,0,0,0,1,1,2};
//这里的dx,dy的意思是他在二维矩阵所做出的动作
static int max_length = Integer.MIN_VALUE;//先定义一个变量求最长度,即题目所需的总权值和最大
public static void main(String[] args) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = sr.nextInt();//输入每个点的权值
}
}
dfs(0,0, map[0][0]);//map[0][0]表示第一个点的权值
System.out.println(max_length);
}
private static void dfs(int i, int j, int length) {
if(i==n-1 && j== m-1)
max_length = Math.max(length, max_length);//这里是求最长的长度,即最大的权值和,将每一次的权值和length进行比较,得出最大的一个。
for (int k = 0; k < dx.length; k++) {
int nx = i + dx[k];//对每一个点进行递归,遍历dx[]中每一个数
int ny = j + dy[k];//对每一个点进行递归,遍历dy[]中每一个数
//(nx,ny),(0,1)(0,2)(0,3)(1,0)(2,0)(3,0)(1,1)(2,1)(1,2)
if (nx >= 0 && ny >= 0 && nx < n && ny < m ) {
dfs(nx,ny,length+map[nx][ny]);//将nx,ny赋值给i,j再次进行循环,同时计算出每一次路径的权值
}
}
}
}
11.数的分解
题目描述
运行限制
代码解析
这一题的思路主要是定义三个数,i,j,k,根据题目要求交换3个整数的顺序视为同一种方法,所以我们令i<j<k,同时构造方法isTrue判断i,j,k中是否有数字为2或者4,如果没有则返回值,对sum进行++统计次数。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
int sum=0;
for(int i=1;i<2019/2;i++){
for(int j=i+1;j<2019;j++){
int k=2019-i-j;
if((i<j)&&(j<k)){
if(isTrue(i)&isTrue(j)&isTrue(k)){
sum++;
}
}
}
}
System.out.println(sum);
}
public static boolean isTrue(int n){
String str=n+"";
for(int i=0;i<str.length();i++){
if(str.charAt(i)=='2'||str.charAt(i)=='4'){
return false;
}
}
return true;
}
}
12.猜生日
题目描述
运行限制
代码解析
题还是比较简单的,需要注意的是求日期的那里需要加个判断条件,当日小于10的时候要多加一个0在前面,否则运行不出来。
import java.util.Scanner;
//1:无需package
//2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
String num3;
String num2="06";
for(int i=1900;i<2012;i++){
String num1=i+"";
for(int j=1;j<=30;j++){
if(j<10){
num3="0"+j+"";
}
else{
num3=j+"";
}
String num4=num1+num2+num3;
int x=Integer.parseInt(num4);
if(x%2012==0 && x%3==0 && x%12==0){
System.out.println(x);
}
}
}
}
}
13.成绩统计
题目描述
输入描述
输出描述
输入输出样例
运行限制
代码解析
3.这题需要注意结果求及格率的时候,要加上优秀的人,同时对人数*100再进行整除。这题我筛选优秀的条件没有=85,导致通过率只有10%,如果漏了=,结果虽然是对的,但是通过不了
import java.util.Scanner;
//1:无需package
//2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
double sum=0;
double count=0;
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
for(int i=1;i<=n;i++){
int m=sc.nextInt();
if(m>=60&&m<85){
sum+=1;
}else if(m>=85){
count+=1;
}
}
System.out.println(Math.round((sum+count)*100/n)+"%");
System.out.println(Math.round(count*100/n)+"%");
sc.close();
}
}
14.最大和
问题描述
输入格式
输出格式
样例
评测用例
运行限制
代码解析
动态规划问题需要对初始值进行初始化,求最小质因子最好是另外定义一个方法。dp解题套路。
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] a = new int[n + 1];//各个方格的分值
int[] dp = new int[n + 1];//走到各个方格的最大值
for (int i = 1; i <=n ; i++) {
a[i]=scan.nextInt();
}
Arrays.fill(dp,Integer.MIN_VALUE);
dp[1]=a[1]; //默认站在第1个方格
//遍历所有到n的路径
for (int i = 1; i <=n ; i++) {
int next=findMinNumber(n-i);
//遍历当前方格可以走的路径
for (int j = i+1; j <=i+next ; j++) {
//存下最大值
dp[j]=Math.max(dp[j],dp[i]+a[j]);
}
}
System.out.println(dp[n]);
// Arrays.stream(dp).skip(1).forEach(x->{
// System.out.print(x+" ");
// });
}
//找出x的最小质因数
public static int findMinNumber(int x){
for (int i = 2; i <=Math.sqrt(x); i++) {
if(x%i==0){
return i;
}
}
return x;
}
}
15.星期计算
题目描述
运行限制
代码解析
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
int a=20;
int b=22;
int k=(int)Math.pow(20,22);
int j=k%7;
System.out.println(6+j);
}
}
16.考勤刷卡
问题描述
输入格式
输出格式
样例输入评测
代码解析
本题主要用到ArrayList,TreeSet,TreeSet主要是对添加进的数进行排序,最后用一个循环将id进行输出(Integer:TreeSet)
import java.util.Scanner;
import java.util.ArrayList;
import java.util.TreeSet;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//在此输入您的代码...
ArrayList<String> str=new ArrayList<>();
TreeSet<Integer> id=new TreeSet<>();
int n=sc.nextInt();
for(int i=0;i<n;i++){
str.add(sc.next());
id.add(sc.nextInt());
}
for(Integer a:id){
System.out.println(a);
}
sc.close();
}
}
17.卡片
问题描述
输入格式
输出格式
样例评测
代码解析
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
int k=0;
while(n>0){
k++;
n=n-k;
}
System.out.println(k);
sc.close();
}
}
18. 三角回文数
问题描述
答案提交
代码解析
这道题构造好判断是否为回文数就很简单了,构造方法中我不知道用什么条件来判断 ,看了题解才知道,将一个整数转换成字符串,利用char arr[ ]=s.toCharArray( );将字符串对象中的字符转换为一个字符数组,这样我们就可以方便获取长度,实现判断是否为回文数。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Huiwen {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int j=0;
for(int i=1;i<=20220514;i++){
j+=i;
if(j>20220514&&huiwen(j)){
System.out.println(j);
break;
}
}
sc.close();
}
public static boolean huiwen(int k){
String arr=k+"";
char[] c=arr.toCharArray();
for(int i=0;i<c.length/2;i++){
if(c[i]!=c[c.length-i-1]){
return false;
}
}
return true;
}
}
19.数数
问题描述
答案提交
代码解析
这道题我看了题解才想起来要用while循环,而且自己在用for循环的时候没有对n/i导致算出的因子没有相加,始终等于1。这道题做起来不难,主要是要细心,而且要判断当n=5的时候,这时候它本身为一个因子,所以要另外对因子个数+1.
import java.util.Scanner;
//1:无需package
//2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
int sum=0;
for(int i=2333333;i<=23333333;i++){
if(zhishu(i)){
sum++;
}
}
System.out.println(sum);
}
public static boolean zhishu(int n){
int count=0;
for(int i=2;i<=Math.sqrt(n);i++){
while(n%i==0){
count++;
n/=i;
}
}
if(n>1){
count++;
}
if(count==12){
return true;
}
return false;
}
}
20.数组切分
问题描述
输入格式
输出格式
样例及评测
代码解析
dp[i]的定义,表示以i结尾的数组段
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//返回有几种切分方法
int n = scanner.nextInt();
int []num = new int[n+1];
for(int i = 1;i<=n;i++) {
num[i] = scanner.nextInt();
}
int mod = 1000000007;
//dp[i]:以i下标结尾的数组段中的分割方法数
int []dp = new int[n+1];
//初始化:
dp[0] = 1;
//遍历顺序
for(int i = 1;i<=n;i++) {
int max = num[i];
int min = num[i];
//从当前位往后遍历找最大值最小值
for(int j = i;j<=n;j++) {
max = Math.max(max, num[j]);
min = Math.min(min, num[j]);
// 如果当前的最大值和最小值之差等于当前的数字个数,则说明当前的数字可以切分
if(j-i==max-min) {
// 切分的方法数量为当前的数字个数加上之前的方法数量
//状态转移方程:当前段数=(i到j分一段)+(i之前的段数)
dp[j] = (dp[j] + dp[i-1])%mod;
}
}
}
System.out.println(dp[n]);
}
}
21.倍数问题
题目描述
输入描述
输出描述
样例
代码解析
三层循环,找出所有三三组合。不是百分百通过率,能骗点分。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int count=0;
int n=scan.nextInt();
int K=scan.nextInt();
int []arr=new int[n+1];
for(int i=1;i<=n;i++){
arr[i]=scan.nextInt();
}
for(int i=0;i<arr.length-2;i++){
for(int j=i+1;j<arr.length-1;j++){
for(int k=j+1;k<arr.length;k++){
int num=arr[i]+arr[j]+arr[k];
if(num%K==0){
if(num>count){
count=num;
}
}
}
}
}
System.out.println(count);
scan.close();
}
}
总结
这一周是我学的最认真的一周,也是学到最多东西的一周,想起之前每天为了想通一道题而忘记吃饭,还是令人回味,算法是一件有意思的事情,但难在每天的坚持。脚踏实地,志存高远,希望有一天能为自己所做的事情而感到骄傲。