写在前面:

        写这篇主要是复习的时候好复习(突然发现记博客的好处就是随时随地可以看,还不占空间内存),暂时只记了ABCFG这五题,如果想看所有题目的可以直接点击上面别人大佬的链接,就不用点击关注我了(设个关注仅仅只是我很菜,还是不要出来乱晃了,当然有大佬想看我的题解欢迎不吝赐教)

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_蓝桥杯大赛历年真题javab组

public static void main(String[] args) {
	long y=494805L,temp = 0,ans;
	while(y<=1000000007L) {
		ans=y;
		temp=y*2021;
		temp=temp%1000000007L;
		if(temp == 999999999L) {
			System.out.println(ans);
			break;
		}
		y++;
	}
	if(y==1000000008) {
		System.out.println(y);
	}
}

 答案:17812964

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_java_02

package bluebridge;

import java.math.*;
import java.util.HashSet;
import java.util.Set;

public class Main {
	public static void main(String[] args) {
		Point []arr =new Point[450];
		int num=1,x1,x2,y1,y2,a,b,c,gcdd,total=0;
		Set<String> tmpSet=new HashSet<>();
		String s;
		for (int i = 0; i < 20; i++) {
			for (int j = 0; j < 21; j++) {
				arr[num]=new Point();		
				arr[num].setX(i);
				arr[num].setY(j);
				num++;
			}
		}	
		
		for (int i = 1; i < num; i++) {
			for (int j = 1; j < num; j++) {
				//把重复的点去掉
				if ((arr[i].getX()==arr[j].getX())&&(arr[i].getY()==arr[j].getY())) {
					continue ;
				}
				x1=arr[i].getX();
				x2=arr[j].getX();
				y1=arr[i].getY();
				y2=arr[j].getY();
				a=y1-y2;
				b=x2-x1;
				c=x1*y2-x2*y1;
				gcdd=gcd(gcd(a,b),c);
				s=a/gcdd+" "+b/gcdd+" "+c/gcdd;
				if(tmpSet.add(s)==true) {
					total++;
				}
				
			}
			
		}
		
	
		System.out.println(total);
		
	}
	
	public static int gcd(int a,int b) {
		return b==0?a:gcd(b, a%b);
	}
}

class Point{
	int x;
	int y;
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
}

 答案:40257

 思路:

  • 创造一个类来表示坐标
  • 使用数组将所有点存在一起
  • 直线的两点式展开,分别算出a,b,c

            (y1-y2) * x +(x2-x1) * y +( x1 * y2 - x2 * y1)=0,分别对应a,b,c (注意为了确定唯一性,进行约分)

  • 将a,b,c拼接并存入set集合,存了多少次就说明有多少条直线

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_java_03

package bluebridge;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class Main {
	public static void main(String[] args) {
		String sn="2021041820210418",tmpString;   //练习一下string转其他类型,当然也可以直接在后面加L
		Long ln=Long.valueOf(sn);
		long n=ln.longValue();	
		long tmp=(long) Math.sqrt(n);
		
	    ArrayList<Long> yinzi=new ArrayList<>();   //用来存所要求的数的因子
	    Set<String> anSet= new HashSet<>();        //存组合情况
	    
	    for (long i = 1; i <= tmp; i++) {          //求所有因子
			if ((n%i)==0) {
				yinzi.add(i);
				yinzi.add(n/i);
			}
		}
	
	    for (int i = 0; i < yinzi.size(); i++) {
	    	for (int j = 0; j < yinzi.size(); j++) {
				if((yinzi.get(i)*yinzi.get(j))<=n) {
					for(int k = 0; k < yinzi.size(); k++) {
						if((yinzi.get(i)*yinzi.get(j)*yinzi.get(k))==n) {
							tmpString=yinzi.get(i).toString()+" "
						           +yinzi.get(j).toString()+" "+
						           yinzi.get(i).toString();
							anSet.add(tmpString);
						}
					}
				}
			}
			
		}
	    System.out.println(anSet.size());
	    
	    
	    
	}

}

 答案:2430

 思路:

其实这题本质是因子分解,相当于求一个数可以分解为多少种由三个数组合而成的情况,把该数所有因子求出来,然后暴力组合就行了。

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_java_04

 

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_蓝桥杯大赛历年真题javab组_05

package bluebridge;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {
	public static void main(String[] args) {
		int n,i=1,ans=1,tmp=1;
		ArrayList<Integer> arr=new ArrayList<>();
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		sc.close();
		arr.add(1);
		
		while(i<n) {
			i=tmp+1;
			if(i>=n) {
				break;
			}
			arr.add(i+arr.get(arr.size()-1));
			tmp=tmp*3+1;
		}
		
		System.out.println(arr.size());
	}
	
}

做题链接: 

蓝桥杯2021年第十二届省赛真题-最少砝码 - C语言网 (dotcpp.com)https://www.dotcpp.com/oj/problem2612.html思路:

贪心思想:假设如果要表示的重量为2,可以用1+1,或者1+2,或者1+3来表示,那么为什么不选择能表示重量最大的那个组合呢。

找规律:

n能表示最大重量的组合最大能表示到max11121  3451  3  913141  3  9  2740.........

由上可以看出:

 max=max*3+1

 n=上一个max+1

每次新增的砝码的重量=n+上一个max

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_i++_06

 

蓝桥杯大赛历年真题javab组 蓝桥杯java a组真题_java_07

 代码:

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	static int n;
	static int x;
	static ArrayList<Integer>[] arr;
	
	public static void main(String[] args) 
	{
		int ans;
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		arr=new ArrayList[n+2];

		for (int i = 1; i <= n; i++) {
			arr[i]=new ArrayList<>();
		}	
		
		for (int i = 2; i <= n; i++) {
			x=sc.nextInt();
			arr[x].add(i);
		}
		
		ans=dfs(0,1);
		System.out.println(ans);
		
		
		/*for (int i = 1; i <= n; i++) {
			for (int j = 0; j < arr[i].size(); j++) {
				System.out.print(arr[i].get(j)+"****");
			}
			System.out.println();
		}*/	
		}
	
	public static int dfs(int total,int i) {
		if(arr[i].size()!=0) {
			int tmpp=0,tmp=0;
			for (int j = 0; j < arr[i].size(); j++) {
				tmp=dfs(total, arr[i].get(j));
				if(tmp>tmpp) {
					tmpp=tmp;
				}				
			} 
			return total+tmpp+arr[i].size();
		}
		else return arr[i].size();
	}
		
	}

思路:

看了好几遍题目才懂什么意思,通俗来讲就是左边可以放该节点的孩子,而右边放该节点的兄弟,所以说一个节点的右孩子的右孩子的右孩子(假设叫兄弟链)...他们全都是兄弟。从题目可以看出,要让深度最长,就要使有孩子的节点x尽量放在兄弟链的最低端,以避免它的孩子和它的兄弟平级了而浪费了一个深度。

然后可以从最简单子树开始往上长,一个一个子树的去判断,有众多兄弟的,选择以它作为根节点,高度最长的子树放在最下面,以此类推,就dfs。

未完待续...