【冲刺蓝桥杯Java组】22个蓝桥杯常见算法知识点模板总结

1.因数分解(不包含因子是1的分解)

public class Main {   
    public static int n;
    public static int total=0;
    public static void  f(int n)
    {
    	if(n==1) total++;
    	for(int i=2;i<=n;i++)
    	{
    		if(n%i==0) 
    			f(n/i);
    	}
    }
	public static void main(String[] args) throws FileNotFoundException 
	{  
    Scanner cin=new Scanner (System.in);
    n=cin.nextInt();
    f(n);
    System.out.println(total);
    }   
}

2.半数集问题
半数集指的是在一个自然数左边加上不超过这个数一半的数而组成的集合
公式:
f(n)=sum(f(n/2))+1
这里sum是求和函数

public class Main {   
    public static int n;
    public static int total=0;
    public static int f(int n)
    {
    	int res=1;
    	for(int i=1;i<=n/2;i++)
    	{
    		res+=f(i);
    	}
    	return res;
    }
	public static void main(String[] args) throws FileNotFoundException 
	{  
    Scanner cin=new Scanner (System.in);
    n=cin.nextInt();
    System.out.println(f(n));
    }   
}

3.快速幂

public class Main {   
    public static long  a;
    public static long  n;
    public static long  p;
	public static void main(String[] args) throws FileNotFoundException 
	{  
    Scanner cin=new Scanner (System.in);
    a=cin.nextLong();n=cin.nextLong();p=cin.nextLong();
    mod_pow(a,n,p);
    }
	private static void mod_pow(long a2, long n2, long p2) {
		// TODO Auto-generated method stub
		long res=1;
		while(n2>0)
		{
			if((n2&1)==1) res=res*a2%p2;
			a2=a2*a2%p2;
			n2=n2>>1;
		}
		System.out.println(res);
	}   
}

4.辗转相除法(求最大公约数)

public class Zz {   
    public static long  a;
    public static long  b;
    public static long gcd(long  a,long  b)
    {
    	if(b==0) return a;
    	else return gcd(b,a%b);
    }
    public static void main(String[] args) throws FileNotFoundException 
	{  
    Scanner cin=new Scanner (System.in);
    a=cin.nextLong();
    b=cin.nextLong();
    System.out.println(gcd(a,b));
	}   
}

求最小公倍数

public class Zz {   
    public static long  a;
    public static long  b;
    public static long gcd(long  a,long  b)
    {
    	if(b==0) return a;
    	else return gcd(b,a%b);
    }
    public static long lcm(long a,long b)
    {
    	return a/gcd(a,b)*b;
    }
    public static void main(String[] args) throws FileNotFoundException 
	{  
    Scanner cin=new Scanner (System.in);
    a=cin.nextLong();
    b=cin.nextLong();
    System.out.println(lcm(a,b));
	}   
}

5.杨辉三角求组合数学(更多杨辉三角问题请看我之前的博客组合数之杨辉三角)

public class Zz {   
  
   public static int [][]arr=new int [20000][20000];
	public static void get_C(){
	    for(int i = 1; i <= 10000; i++){
	        for(int j = 1; j <= 10000; j++){
	            if(j == 1) arr[i][j] = i;
	            else arr[i][j] = (arr[i-1][j] + arr[i-1][j-1])%1000000007;
	        }
	    }
	}

    public static void main(String[] args) throws FileNotFoundException 
	{  
    Scanner cin=new Scanner (System.in);
    get_C();
    System.out.println(arr[5][3]);
    
	}   
}

6.因数存放模板
long 最高位数是19位,2021041820210418的因数一共有128个,三次循环即可,真恶心呀

long  n;
      n=cin.nextLong();
      ArrayList<Long> a=new ArrayList<>();
      for(long i=1;i<=Math.sqrt(n);i++)
      {
    	  if(n%i==0) 
    	  {
    		  a.add(i);
    		  if(i!=n/i)
    		  {
    			  a.add(n/i);
    		  }
    	  }
      }

例题

public class Main {   
    public static void main(String[] args) throws FileNotFoundException 
	{  
      Scanner cin=new Scanner (System.in);
      long  n;
      n=cin.nextLong();
      ArrayList<Long> a=new ArrayList<>();
      for(long i=1;i<=Math.sqrt(n);i++)
      {
    	  if(n%i==0) 
    	  {
    		  a.add(i);
    		  if(i!=n/i)
    		  {
    			  a.add(n/i);
    		  }
    	  }
      }
      int sum=0;
      for(int  i=0;i<a.size();i++)
      {
    	  for(int j=0;j<a.size();j++)
    	  {
    		  for(int z=0;z<a.size();z++)
    		  {
    			  if(a.get(i)*a.get(j)*a.get(z)==n)
    			  {
    				  sum++;
    			  }
    		  }
    	  }
      }
      System.out.println(sum);
      
	}   
}	

7.二分(整数和实数二分)
例题

public class Main {   
   
    public static  int n,k;
    public static void main(String[] args) throws FileNotFoundException 
	{  
      Scanner cin=new Scanner (System.in);   
      n=cin.nextInt();
      k=cin.nextInt();
      int [][]a=new int [200000][2];
      for(int i=1;i<=n;i++)
      {
    	  a[i][0]=cin.nextInt();
    	  a[i][1]=cin.nextInt();
      }
      int l=1;
      int r=100000;
      while(l<=r)
      {
    	  int mid=(l+r)/2;
    	  if(check(a,mid,k)) l=mid+1;
    	  else r=mid-1;
      }
     System.out.println(r);
	}

	private static boolean check(int[][] a, int mid, int k) {
		// TODO Auto-generated method stub
		int count=0;
		for(int i=1;i<=n;i++)
		{
			int x=(a[i][0]/mid)*(a[i][1]/mid);
			count+=x;
		}
		return count>=k;
	}   
}

实数二分

import java.util.Scanner;
public class Main {

  static double n, l, r, mid;
  static double eps = 1e-8;
  static boolean pd(double a, int m) {
      double c = 1;
      while (m > 0) {
          c = c * a;
          m--;
      }
      if (c >= n)
          return true;
      else
          return false;
  }
  public static void main(String[] args) {
      int m;
      Scanner in =new Scanner(System.in);
      n=in.nextDouble();
      m=in.nextInt();
//设置二分边界
      l = 0;
      r = n;
//实数二分
//不能加上等于
      while (l + eps < r) {
          double mid = (l + r) / 2;
          if (pd(mid, m))
              r = mid;
          else
              l = mid;
      }
      System.out.println(String.format("%.7f",l));
  /*
   关于string.format 的应用

  double num = 123.4567899;
  System.out.print(String.format("%f %n", num)); // 123.456790
  System.out.print(String.format("%a %n", num)); // 0x1.edd3c0bb46929p6
  System.out.print(String.format("%g %n", num)); // 123.457

  可用标识:

        -,在最小宽度内左对齐,不可以与0标识一起使用。
        0,若内容长度不足最小宽度,则在左边用0来填充。
        #,对8进制和16进制,8进制前添加一个0,16进制前添加0x。
        +,结果总包含一个+或-号。
        空格,正数前加空格,负数前加-号。
        ,,只用与十进制,每3位数字间用,分隔。
        (,若结果为负数,则用括号括住,且不显示符号。

  可用转换符:

        b,布尔类型,只要实参为非false的布尔类型,均格式化为字符串true,否则为字符串false。
        n,平台独立的换行符, 也可通过System.getProperty("line.separator")获取。
        f,浮点数型(十进制)。显示9位有效数字,且会进行四舍五入。如99.99。
        a,浮点数型(十六进制)。
        e,指数类型。如9.38e+5。
        g,浮点数型(比%f,%a长度短些,显示6位有效数字,且会进行四舍五入)
   */
  }
}

8.四平方和定理(stl应用)
x=aa+bb+cc+dd
因为由小到大排序,所以先算cd和ab

import java.math.*;
import java.io.*;
import java.math.*;
import java.util.Scanner;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Collection;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util. Iterator;

class Node
{
	int c;
	int d;
	public Node(int c,int d)
	{
		this.c=c;
		this.d=d;
	}
}
public class Main {   
      
    static  Map<Integer,Node>m=new HashMap<>();
    public static void main(String[] args) throws FileNotFoundException 
	{  
     Scanner cin=new Scanner(System.in);
     int n;
     n=cin.nextInt();
     for(int c=0;c*c<=n;c++)
     {
    	 for(int d=0;c*c+d*d<=n;d++)
    	 {
    		 int res=c*c+d*d;
    		 if(m.containsKey(res)==false)
    		 {
    			 m.put(res, new Node(c,d));
    		 }
    	 }
     }
     for(int a=0;a*a<=n;a++)
     {
    	 for(int b=0;a*a+b*b<=n;b++)
    	 {
    		 int res2=n-a*a-b*b;
    		 if(m.containsKey(res2)==true)
    		 {
    			 
    			 System.out.println(a+" "+b+" "+m.get(res2).c+" "+m.get(res2).d);
    			 System.exit(0);
    		 }
    	 }
     }
     cin.close();
	}
}

9.时间类问题(蓝桥杯常考的第一题)

Calendar API:月份从0开始,星期日为1(之后一次+1)

(1)

小蓝要和朋友合作开发一个时间显示的网站。在服务器上,朋友已经获取 了当前的时间,用一个整数表示,值为从 1970 年 1 月 1 日
00:00:00 到当前时 刻经过的毫秒数。
现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要 显示出时分秒即可,毫秒也不用显示,直接舍去即可。
给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

import java.util.Scanner;
 
public class 时间显示 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		long n=sc.nextLong();
		//拿到的是毫秒,先转换为秒,1m等于1000ms
		n=n/1000;
		//现在拿到的是秒,对一天的秒数取余即可获得今天的秒数
		n=n%(60*60*24);
		//现在拿到的是一天的秒数,开始转化为答案,一小时有3600秒,先获得秒
		long hour=n/3600;
		//现在获得分钟加分
		n%=3600;
		//再获得分钟
		long month=n/60;
		//再获得秒
		n%=60;
		long s=n;
		//这里涉及输出格式,大家可以学习一下printf的输出格式
		System.out.printf("%02d:%02d:%02d",hour,month,s);	
	}
}

(2)

    1999年12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即XX99年)的12月31日正好是星期天(即星期日)? 回答年份即可        

public class Main {   
  	public static void main(String[] args) throws FileNotFoundException 
	{         
	Scanner cin=new Scanner(System.in);   
    Calendar a=Calendar.getInstance();
    int year,yue,ri;
    for(int i=1999;;i+=100)
    {
    	a.set(Calendar.YEAR, i);
    	a.set(Calendar.MONTH, 11);
    	a.set(Calendar.DAY_OF_MONTH, 31);
    	if(a.get(Calendar.DAY_OF_WEEK)==1)
    	{
    		System.out.println(i);
    		return;
    	}
    }
	}
}

(3)跑步锻炼

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(2000, 0, 1);
//        calendar.set(Calendar.YEAR, 2000);
//        calendar.set(Calendar.MONTH, 0);
//        calendar.set(Calendar.DAY_OF_MONTH, 1);
        int count = 0;
        while (true) {
            calendar.add(calendar.DAY_OF_YEAR,1);
            if (calendar.get(calendar.DAY_OF_WEEK) == 2 || calendar.get(calendar.DAY_OF_MONTH) == 1 ){
                count += 2;
            }else {
                count ++;
            }
            if (calendar.get(calendar.YEAR) == 2020 && calendar.get(calendar.MONTH) == 9 && calendar.get(calendar.DAY_OF_MONTH) == 2) {
                break;
            }
        }
        System.out.print(count + 1);
    }
}

10.求从1到n的最小公倍数(大数模板题)
题目链接

import java.math.*
import java.io.*;
import java.math.*;
import java.util.Scanner;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Collection;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util. Iterator;
public class Main {   
      
    public static  int a,b,t;
    public static void main(String[] args) throws FileNotFoundException 
    {  
      Scanner cin=new Scanner (System.in);
      int n;
      n=cin.nextInt();
      BigInteger res;
     BigInteger []a=new BigInteger [105];
     for(int i=1;i<=n;i++)
     {
         a[i]=BigInteger.valueOf(i);
     }
    for(int i=1;i<n;i++)
     {
         res=a[i].gcd(a[i+1]);
         a[i+1]=a[i].divide(res).multiply(a[i+1]);
     }
     System.out.print(a[n]);      
    }   
}

11.数字三角形
题目链接

关于向左向右步数不能相差1的理解:

说明最后在最后一层一定会落到中间

所以只需判断最后一层为奇数:中位数(n+1/2)
偶数:中间两个取最大即可

#include 
using namespace std;
int a[200][200],c[200][200],n;
int main()
{
  cin>>n;
  for(int i=1;i<=n;i++)
  for(int j=1;j<=i;j++)
  cin>>a[i][j];
  c[1][1]=a[1][1];
  for(int i=2;i<=n;i++)
  for(int j=1;j<=i;j++)
  c[i][j]=a[i][j]+max(c[i-1][j],c[i-1][j-1]);
  cout<<max(c[n][(n+1)/2],c[n][(n+1)/2+1]);
  return 0;
}

12.java如何保留小数

System.out.printf("%.2f", sum);

13.同余定理
同予定理——想要 b - a为 k 的倍数,只需要确保 b 和 a 模 k 相同即可
k倍区间

import java.math.*;
import java.io.*;
import java.math.*;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Collection;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util. Iterator;
public class Main {   
	public static void main(String[] args) throws FileNotFoundException 
	{         
	Scanner cin=new Scanner(System.in);   
    int n,k;
    n=cin.nextInt();
    k=cin.nextInt(); 
    long ans=0;
    long []a=new long [250000];//前缀和数组
    for(int i=0;i<n;i++)
    {
    	long x=cin.nextLong();
    	a[i+1]=a[i]+x;
    }
    Map<Long,Integer>m=new HashMap<>();
    m.put(0l, 1);//这个意思是放键0(long),值为1
    //System.out.println(m.containsKey(0l));
    for(int i=1;i<=n;i++)
    {
    	ans+=m.getOrDefault(a[i]%k, 0);
        m.put(a[i]%k,m.getOrDefault(a[i]%k, 0)+1);//这里我解释一下:假设我们前缀和数组a[1]=1,a[2]=1,此时键1对应的值为1(ans=1)同时a[3]=1,此时键1对应的值为2(ans=1+2)
        //n2-n1==n3-n2==n3-n1=a[1]%k
    }
    System.out.println(ans); 
	}
}

14、蛇形数组
例题

  int ans = 20 * 20 + 19 * 19;//n^2+(n-1)^2
#include <iostream>
using namespace std;
int main()
{ int sum=1;
  for(int i=1;i<=20;i++)
  {
    sum+=4*(i-1);
  }
  cout<<sum;
}
#include
using namespace std;

int mp[200][200], row = 0, col = 0, cnt = 1;

int main() {
    mp[0][0] = 1;
    while(!mp[19][19]) {
        //右移
        mp[row][++col] = ++cnt;
        //左下方
        while(col) {
            mp[++row][--col] = ++cnt;
        }
        //下移
        mp[++row][col] = ++cnt;
        //右上方
        while(row) {
            mp[--row][++col] = ++cnt;
        }
    }
    /*for(int i = 0; i < 20; i++) {
        for(int j = 0; j < 20; j++) {
            cout << mp[i][j] << "  ";
        }
        cout << endl;
    }*/
    cout << mp[19][19];
    return 0;
}

15.数论知识
(1)例题

对于互质的两个数a和b,其不能组成的最大整数为a*b-a-b

System.out.println(n*m-n-m);

持续更新。。。。
16.如何判断一个区间,经过递增排列后是一个连续的区间

max-min=j-i

17.二分查找模板
private static int test2(int[] a,) {
int l=1;
int mid;
int r=a.length;
while(l<=r)
{
mid=(l+r)>>1;
if(…) l=mid+1;//
else r=mid-1;
}
return r+1;//永远返回if条件的另一个
}

private static int test2(int[] a, int i) {
		int l=1;
		int mid;
		int r=a.length;
		while(l<=r)
		{
			mid=(l+r)>>1;
		    if(a[mid]<=i) l=mid+1;
		    else r=mid-1;
		}
		return r+1;
	}
	private static int  test1(int[] a2, int target) {
		// TODO Auto-generated method stub
		int l=1;
		int mid;
		int r=a2.length;
		while(l<=r)
		{
			mid=(l+r)>>1;
		    if(a2[mid]<target) l=mid+1;
		    else r=mid-1;
		}
		return r;
	}
	System.out.print(test1(a,5));//最后一个小于5的max数
	System.out.print(test2(a,5));//第一个大于5的数

18.DFS历年常见题目
A.试题 历届真题 全球变暖【第九届】【省赛】【B组】

public class Main {   
   	public static int n;
	public static int visited[][]=new int [1500][1500];
    public static boolean flag=false;
    public static int[] dix= {1,-1,0,0};
    public static int [] diy= {0,0,1,-1};
	public static void main(String[] args) throws FileNotFoundException 
	{     
   	Scanner cin=new Scanner(System.in);  
   
   	int ans=0;
   	n=cin.nextInt();
   	char [][]a=new char[2500][2500];
   	for(int i=0;i<n;i++)
   	{
   		a[i]=cin.next().toCharArray();
   	}
   	for(int i=0;i<n;i++)
   	{
   		for(int j=0;j<n;j++)
   		{
   			if(a[i][j]=='#'&&visited[i][j]==0)
   			{
   				dfs(a,i,j);
   				if(flag==false)
   				{
   					ans++;
   				}
   				flag=false;
   			}
   		}
   	}
   	System.out.println(ans);
}
	private static void dfs(char[][] a, int i, int j) {
		// TODO Auto-generated method stub
	    if(a[i+dix[0]][j+diy[0]]=='#'&&a[i+dix[1]][j+diy[1]]=='#'&&a[i+dix[2]][j+diy[2]]=='#'&&a[i+dix[3]][j+diy[3]]=='#')
	    {
	    	flag=true;
	    }
		visited[i][j]=1;
		for(int k=0;k<4;k++)
		{
			int newx=i+dix[k];
			int newy=j+diy[k];
			if(a[newx][newy]=='#'&&visited[newx][newy]==0&&newx>=0&&newy>=0&&newx<n&&newy<n)
			{
         	dfs(a,newx,newy);		
			}   	
		
	}
	
}
}

B. 全排列



public class Zz {   
    
	public static int maxn=0;
	public static int arr[]= {1,2,3,4,5,6,7,8,9};
	public static void dfs(int k)
	{
		if(k==9)
		{
			for(int i=0;i<=8;i++)
			{
				System.out.print(arr[i]+"   ");
			}
			System.out.println();
			return ;
		}
		for(int i=k;i<=8;i++)
		{
			swap(k,i);
			dfs(i+1);
			swap(k,i);
		}
	}
	
	private static void swap(int k, int i) {
		int temp;
		temp=arr[k];
		arr[k]=arr[i];
		arr[i]=temp;
	}
	public static void main(String[] args) 
	{     
    dfs(0);
       }
}

最大乘积

import java.util.HashSet;
import java.util.Set;
 
public class 最大乘积 {
	static int max=0;
	static int[] arr= {1,2,3,4,5,6,7,8,9};
	public static void main(String[] args) {
		dfs(0);
		System.out.println(max);
	}
	//全排列
	static void dfs(int k) {
		if(k==9) {
			check();
			return;
		}
		for(int i=k;i<arr.length;++i) {
			exch(i,k);
			dfs(k+1);
			exch(i,k);
		}
	}
	//插入乘号位置
	static void check() {
		for(int i=1;i<=8;++i) {
			int a=test(arr,i);
			if(isOk(a)) {
				max=Math.max(a,max);
			}
		}
	}	
	//获取乘积
	static int test(int[] arr,int k) {
		int pre=0;
		int count1=0;
		while(k-->0) {
			count1=count1*10+arr[pre];
			pre++;
		}
		int count2=0;
		for(int i=pre;i<arr.length;++i) {
			count2=count2*10+arr[i];
		}
		return count1*count2;
	}
	//判断答案是否有且仅包含1~9
	static boolean isOk(int n){
		Set<Integer> set=new HashSet<>();
		for(int i=1;i<=9;++i) set.add(i); 
		while(n!=0) {
			int a=n%10;
			if(!set.contains(a)) return false;
			else set.remove(a);
			n/=10;
		}
		return set.size()==0;
	}
	//交换函数
	static void exch(int a,int b) {
		int tmp=arr[a];
		arr[a]=arr[b];
		arr[b]=tmp;
	}
}

19.暴力枚举以及找规律题
1.等差素数列
2.最少砝码
20.STL
(1)
砝码称重
注意: ArrayListlist=new ArrayList<>(s)【Set的名字】
链表复用Set

import java.math.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util. Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class Main {   	
	public static void main(String[] args) 
	{     
	Scanner cin=new Scanner (System.in);
    int n;
    n=cin.nextInt();
    int []a=new int [120];
    for(int i=1;i<=n;i++)
    	a[i]=cin.nextInt();
    Set<Integer>s=new HashSet<>();
    s.add(0);
    for(int i=1;i<=n;i++)
    {
    	ArrayList<Integer>list=new ArrayList<>(s);
    	for(int k=0;k<list.size();k++)
    	{
    		s.add(list.get(k)+a[i]);
    		s.add(Math.abs(list.get(k)-a[i]));
    	}
    }
    s.remove(0);
    System.out.println(s.size());    
	}	
}

21.前缀和和差分模板
转载
一维差分模板题:小明的彩灯

import java.util.Scanner;
public class Main {   	
	public static int []b=new int [550000];
	public static void main(String[] args) 
	{     
	Scanner cin=new Scanner (System.in);
    int n,q;
    n=cin.nextInt();
    q=cin.nextInt();
    int []a=new int [550000];
    for(int i=1;i<=n;i++)
    	a[i]=cin.nextInt();
    for(int i=1;i<=n;i++)
    {
    	b[i]=a[i]-a[i-1];
    }
    int l,r,m;
    for(int i=1;i<=q;i++)
    {
    	l=cin.nextInt();r=cin.nextInt();m=cin.nextInt();
    	b[l]+=m;
    	b[r+1]-=m;
    }
    for(int i=1;i<=n;i++)
    {
    	b[i]+=b[i-1];
    }
    for(int i=1;i<=n;i++)
    	b[i]=Math.max(b[i], 0);
    for(int i=1;i<=n;i++)
    {
    	System.out.print(b[i]+" ");
    }    
	}	
}

22.贪心算法
贪心算法

你可能感兴趣的:(蓝桥杯,动态规划,算法,c++,蓝桥杯)