蓝桥杯模板

蓝桥杯

一、语法

1.字符串挨个输入

直接输入到数组 toCharArray()

//数组
char[][] map=new char[10][10];
String temp[] = { "UDDLUULRUL", "UURLLLRRRU", "RRUURLDLRD", "RUDDDDUUUU", "URUDLLRRUU", "DURLRLDLRL",
                "ULLURLLRDU", "RDLULLRDDD", "UUDDUDUDLL", "ULRDLUURRR" };
for (int i = 0; i < 10; i++) {
     map[i] = temp[i].toCharArray();
     System.out.println(map[i]);
}

 Scanner scanner = new Scanner(System.in);
   String[] s = scanner.next().split("/");
   scanner.close();
   String a = s[0];
   String b = s[1];
   String c = s[2];

输出为:

UDDLUULRUL
UURLLLRRRU
RRUURLDLRD
RUDDDDUUUU
URUDLLRRUU
DURLRLDLRL
ULLURLLRDU
RDLULLRDDD
UUDDUDUDLL
ULRDLUURRR

2.数组

数组:
    double [][] list={{180.90,0.88}};

3.判断素数

public static boolean isPrime(int num){
        for(int i = num-1;i>1;i--){
            if(num%i==0)   //大除小
                return false;
        }
        return true;
    }

注意Boolean拼写

4.Java 的输入

Scanner scan=new Sacnner(System.in);
a=scan.nextInt();

5.ArrayList数组队列

ArrayList 是一个数组队列,提供了相关的添加、删除、修改、遍历等功能 https://www.runoob.com/java/java-arraylist.html LocalDate: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型。

objectName: 对象名 mn

Collections是一个工具类,sort是其中的静态方法,是用来对List类型进行排序的,

(1)升序Arrays.sort

Arrays.sort 本身是升序排列

//r是数组
if (p == 0) 
    //倒序排列的用法
    Arrays.sort(r, 1, q + 1, Collections.reverseOrder());//左闭右开
else 
    Arrays.sort(r, q, r.length);//升序

(2)降序

Arrays.sort(r, 1, q + 1, Collections.reverseOrder());//左闭右开

6.日期问题Date

日期问题

   Scanner scanner = new Scanner(System.in);
   String[] s = scanner.next().split("/");
   scanner.close();
   String a = s[0];
   String b = s[1];
   String c = s[2];

输入02/03/04,使用split,可以直接分别存到字符串数组中。

https://blog.csdn.net/weixin_43914593/article/details/112728088

public class A06_航班时间_编程 {
	private static Scanner in;//静态域

	public static void main(String[] args) throws ParseException {
		in = new Scanner(System.in);
		int T=in.nextInt();
		in.nextLine();//去除换行符
		for(int i=0;i<T;i++) {
			long time1=getTime();
			long time2=getTime();
			long t=(time1+time2)/2;
			System.out.printf("%02d:%02d:%02d\n",t/3600,t/60%60,t%60);
		}
	}

	private static long getTime() throws ParseException {
		 String line = in.nextLine();
	     String[] split = line.split(" ");//以空格为分隔符
	     //时间解析的API SimpleDateFormat
	     SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
	     //format.parse(split[0])解析字符串为日期
	     Date t1 = format.parse(split[0]);
	     Date t2 = format.parse(split[1]);
	     
	     int d = 0;
	     if(split.length == 3){
	    	//(+1)   split[2].substring(2,3)  字符串获取1,用Integer 将String转换为整数型
	         d = Integer.parseInt(split[2].substring(2,3));//  split[2].substring(2,3)-'0'
	     }
	     return d*24*3600+t2.getTime()/1000-t1.getTime()/1000;//getTime 得到时间代表的毫秒数
	}
}

7.Math

1.Math.pow(2, 20) 2的20次方

2.Math.round四舍五入

double a=11.5
Math.round(a);
//输出为12

8.BigInteger 大数计算

BigInteger bi1 = new BigInteger("123456789") ;	// 声明BigInteger对象
BigInteger bi2 = new BigInteger("987654321") ;	// 声明BigInteger对象
System.out.println("加法操作:" + bi2.add(bi1)) ;	// 加法操作
System.out.println("减法操作:" + bi2.subtract(bi1)) ;	// 减法操作
System.out.println("乘法操作:" + bi2.multiply(bi1)) ;	// 乘法操作
System.out.println("除法操作:" + bi2.divide(bi1)) ;	// 除法操作
System.out.println("最大数:" + bi2.max(bi1)) ;	 // 求出最大数
System.out.println("最小数:" + bi2.min(bi1)) ;	 // 求出最小数
BigInteger result[] = bi2.divideAndRemainder(bi1) ;	// 求出余数的除法操作
System.out.println("商是:" + result[0] + ";余数是:" + result[1]) ;	

加法操作:1111111110
减法操作:864197532
乘法操作:121932631112635269
除法操作:8
最大数:987654321
最小数:123456789
商是:8;余数是:9

9、无法暴力输出的,直接打印结果

public class Main0{

    public static void main(String[] args) throws Exception {
        int a=100;
    	System.setOut(new PrintStream(new File("E:\\out3.txt")));
        //拦截输入到E盘下的txt中
    	System.out.println(a);
    }
}

10、String

public static void main(String[] args) {
		String mounth;
		mounth=""+1; // 将int型变为字符串
		System.out.println(mounth);
    	Integer.parseInt(mouth)=1//转化为 int 型
	}

(1)string是否包含字符

str='2019'
str.contains("2")//返回是否:true
str.indexOf('2')//返回在第几个位置:0

(2)StringBuilder

一、创建Stringbuilder对象
StringBuilder strB = new StringBuilder();

1append(String str)/append(Char c):字符串连接
System.out.println(StringBuilder:+strB.append(“ch”).append(111).append(‘c’));
//return “StringBuilder:ch111c”

2toString():返回一个与构建起或缓冲器内容相同的字符串
System.out.println(String:+strB.toString());
//return “String:ch111c”

3appendcodePoint(int cp):追加一个代码点,并将其转换为一个或两个代码单元并返回this
System.out.println(StringBuilder.appendCodePoint:+strB.appendCodePoint(2));
//return “StringBuilder.appendCodePoint:ch111c”

4setCharAt(int i, char c):将第 i 个代码单元设置为 c(可以理解为替换)
strB.setCharAt(2, ‘d’);
System.out.println(StringBuilder.setCharAt:+ strB);
//return “StringBuilder.setCharAt:chd11c”

5insert(int offset, String str)/insert(int offset, Char c):在指定位置之前插入字符()
System.out.println(StringBuilder.insertString:+ strB.insert(2, “LS”));
//return “StringBuilder.insertString:chLSd11c”
System.out.println(StringBuilder.insertChar:+ strB.insert(2,L));
//return “StringBuilder.insertChar:chLLSd11c”

6delete(int startIndex,int endIndex):删除起始位置(含)到结尾位置(不含)之间的字符串
System.out.println(StringBuilder.delete:+ strB.delete(2, 4));
//return “StringBuilder.delete:chSd11c”

11、集合

(1)PriorityQueue

是一种基于堆的无界优先级队列。每次弹出的数都是最小的

PriorityQueue<Long> q = new PriorityQueue<Long>() ; 
q.add(num[i]) ; 
long h = q.poll();
q.isEmpty()==false //如果此集合不包含任何元素,则返回 true

(2)Set

Set不包含重复元素的集合。更正式地说,集合不包含一对元素 e1 和 e2 使得 e1.equals(e2),

并且最多包含一个空元素。

Set<Long> st = new HashSet<Long>() ; 
st.add(num[i]);
st.contains(t) //队列是否包含

(3)队列

Queue<Point> queue=new LinkedList<Point>();
queue.add(new Point(x,y));//将起点加入队列
Point first=queue.poll();//弹出头部

二、算法

1、全排列

/**
 * 全排列算法
 */
public class Permutate {
    
    public static int total = 0;
    public static void swap(String []str,int i,int j) {
        String temp = new String();
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }
    
    public static void arrange(String []str,int st,int len) {
        //递归出口
        if(st == len - 1) {
            for (int i = 0;i < len;i ++) {
                System.out.print(str[i] + " ");
            }
            System.out.println();
            total ++;
        }else {
            //全排列递归
            for (int i = st;i < len;i++) {
                swap(str,st,i);
                arrange(str,st+1,len);
                swap(str,st,i);
            }
        }
    }

    public static void main(String[] args) {
        String str[] = {"a","b","c"};
        arrange(str,0,str.length);
        System.out.println(total);
    }
}

自我理解
关键的就是arrange方法的else里面的内容,我的理解是(以求str[] = {“a”,”b”,”c”}的排列为例子):

用i从str[st]做一遍循环:

每一次循环中,都要将str[i]与str[i]互相调换位置:第一次开始,”a”与自己换,这时候,递归调用arrange[str,st + 1, len]

这是在求取str[str…len - 1]的排列即”b”,”c”的排列;

第二次,”a”与”b”互相调换,递归调用arrange[str,str + 1, len]就是在求取{“a”,”c”}的排列。

第三次,”a”与”c”互相调换,递归调用arrange[str, str + 1,len]就是在求取”{“b”,”a}的排列。

下面再以”b”,”c”的排列求取为例:

首先还是做循环,第一次,”b”与自己调换,这时候,调用arrange[str,st + 1,len], 就是求c的排列。呵呵,这时候终于到了函数递归调用的出口了: st = len - 1。输出”b” “c”;

第二次,类似的,输出”c”,”b”;

至此,”b” “c”的排列求取完毕。加上前面的a,就输出”a”“b”“c” “a”“c”“b”。

类似的,就可以输出所有的排列了。

[自我理解部分摘自]http://blog.csdn.net/randyjiawenjie/article/details/6313729

2、矩阵法

最大公共子串长度问题就是: 求两个串的所有子串中能够匹配上的最大长度是多少。
比如:“abcdkkk” 和 “baabcdadabc”, 可以找到的最长的公共子串是"abcd",所以最大公共子串长度为 4。
下面的程序是采用矩阵法进行求解的,这对串的规模不大的情况还是比较有效的解法。

public class A6补充代码_最大公共子串 {
	 static int f(String s1, String s2)
	    {
	        char[] c1 = s1.toCharArray();
	        char[] c2 = s2.toCharArray();
	        int[][] a = new int[c1.length+1][c2.length+1];
	        int max = 0;
         //矩阵法,若有相同飞则变为1,往后的以此加一,不同换到下一行
	        for(int i=1; i<a.length; i++){
	            for(int j=1; j<a[i].length; j++){
	                if(c1[i-1]==c2[j-1]) {
	                    a[i][j] = a[i-1][j-1]+1; 
	                    if(a[i][j] > max) 
	                    	max = a[i][j];
	                }
	            }
	        }
	        return max;
	    }
	    public static void main(String[] args){
	        int n = f("abcdkkk", "baabcdadabc");
	        System.out.println(n);
	        System.out.println(f("aaakkkabababa", "baabababcdadabc"));
	        System.out.println(f("abccbaacbcca", "ccccbbbbbaaaa"));
	        System.out.println(f("abcd", "xyz"));
	        System.out.println(f("ab", "ab"));
	        
	    }

}

abcdkk 与 baabcdadabc

蓝桥杯模板_第1张图片

3、DFS


不带回溯,直接遍历

void dfs(int x,int y){//x、y表示的是坐标点的位置
	if(vis[x][y]) return;//这个表示已经访问过了
	vis[x][y] = true;//如果没有访问过,那么我们现在访问过了
	ans++;
	for(int i = 0;i < 4; ++i) {//这里就是往上下左右四个方向遍历
		int nx = x + dx[i];
		int ny = y + dy[i];
		if(!vis[nx][ny] && nx > 0 && nx <= H && ny > 0 && ny <= W && mp[nx][ny] != '#') {
            //我们这里就是看下一个位置是否能递归访问
			dfs(nx,ny);
		}
	}
}

蓝桥杯模板_第2张图片

题目中已经有明显的暗示——沿着格子边线剪开。
只看每一个格子的顶点及边,可以把整个方格放置到一个二维坐标中,则中心对称点就是(3,3)。
从(3,3)点出发,有四个方向可以走
1.横坐标不变,纵坐标加1
2.横坐标不变,纵坐标减1
3.纵坐标不变,横坐标加1
4.纵坐标不变,横坐标减1
以上的每一个操作,也就对应了代码中的dir数组,尝试每一种方向,变化当前的坐标,并利用辅佐函数标记当前坐标已经被访问过。
同时将其关于(3,3)中心对称的点标记已经访问。(你要想分割出两个完全一样的图形,分割线一定是中心对称的!!!)
一旦走到边界,计数器加一。

package Blue_8;
//DFS 问题

public class A4填空题_方格分割 {
	    private static int[][] ans = new int[7][7];//把方格看成带点 即7x7
	    static int count = 0;
	    static int[][]   dir ={ {0,1} ,{0,-1},{-1,0},{1,0}};//方向 下,上,左,右

	    public static void main(String[] args) {
	        ans[3][3] = 1;
	        dfs(3, 3);
	        System.out.println(count / 4);
	    }

	    private static void dfs(int i, int j) {
	    	//已经走到边界!
	        if (i == 0 || i == 6 || j == 0 || j == 6) {
	            count++;
	            return;
	        }
	        for (int j2 = 0; j2 < 4; j2++) {
	        	 //依次遍历下一个方向
	            int x = i + dir[j2][0];
	            int y = j + dir[j2][1];
	            if (ans[x][y] != 1) {//该点未被访问过    
	                ans[x][y] = 1;//标记为访问
	                ans[6-x][6-y] = 1;//标记对称点
	                dfs(x, y);//深搜
	                ans[x][y] = 0;
	                ans[6-x][6-y] = 0;//回溯
	            }
	        }
	    }
}

4、bfs

模板

思路


由于我们现在的这个问题转变为了最优路径求解,所以我们经量就不要使用DFS(因为递归的过程很耗时间),这个时候就需要BFS(广度优先搜索),什么意思呢,我们尽可能地找到靠近我们当前这个点的周围的点。然后将这个周围的点加入我们即将探寻的这个队列里面。这个过程大概就是一层一层的去访问这些可行的点,这也就是广度优先搜索。

1.我们先将起点放进队列,然后逐步去找起点周围的点,然后将这个周围的点也放进队列,然后将起点移出队首。

2.我们再取出当前队首的点,然后重复上面的过程,直到取出的点是终点。

int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
int bfs(int sx,int sy){
    int cnt = 0;
    q.push(node{sx,sy,0});//压入队列
    while(!q.empty()){//队列不为空
        node p=q.top();//取出队列第一个元素
        q.pop();//弹出
        if(p.x == ex,p.y == ey){//找到终点然后直接返回路径的长度
            return p.k;
        }
        if(vis[p.x][p.y]) continue;//已去过就不去了
        vis[p.x][p.y] = true;//标记已去过
        for(int i=0;i < 4;++i){
           int nx = x + dx[i];
           int ny = y + dy[i];
           if(check(nx,ny)){
               que.push(node{nx,ny,p.k+1});
           }
        }
    }
    return -1;//没有路径的
}

ackage Blue_10;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class A04_迷宫_填空_bfs {
    // 数据存放在这个数组里面
    static String arr1[][] = new String[30][50];
    // {1,0}:下,{0,-1}:左,{0,1}:右,{-1,0}:上
    static int[][] direction1 = { { 1, 0 }, { 0, -1 }, { 0, 1 }, { -1, 0 } };
    static String direction2[] = { "D", "L", "R", "U" };
    // 队列,先进先出
    static Queue<Node> q = new LinkedList<Node>();

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 读取数据
        for (int i = 0; i < 30; i++) {
            arr1[i] = scanner.next().split("");
        }
        
        // 队列q中压入起始结点
        q.offer(new Node(0, 0, ""));
        // 表示该节点已经走过了
        arr1[0][0] = "1";
        BFS();
    }

    static void BFS() {
        int dx, dy;
        while (!q.isEmpty()) {
            // 对手周围尚未压入队列的可抵达的结点压入队列
            Node head = q.poll();//检索并删除此队列的头部,如果此队列为空,则返回 null
            for (int i = 0; i < 4; i++) {
                dx = head.x + direction1[i][0];
                dy = head.y + direction1[i][1];
                
                if (dx == 29 && dy == 49) {//出迷宫则输出
                    System.out.println(head.s + direction2[i]);
                    return;
                }
                // 处理边界问题,放置数组下标越界
                if (dx >= 0 && dy >= 0 && dx <= 29 && dy <= 49 && "0".equals(arr1[dx][dy])) {
                    q.offer(new Node(dx, dy, head.s + direction2[i]));
                    arr1[dx][dy] = "1";
                }
            }
        }
    }
}
class Node {
	int x, y;
	String s;
	public Node(int x, int y, String s) {
		this.x = x;
		this.y = y;
		this.s = s;
	}
}

5、DP

(1)背包 包子凑数

小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 N种蒸笼,其中第 i种蒸笼恰好能放 Ai个包子。

  • 每种蒸笼都有非常多笼,可以认为是无限笼。每当有顾客想买 X个包子,卖包子的大叔就会迅速选出若干笼包子来,
  • 使得这若干笼中恰好一共有 X个包子。
  • 比如一共有 3 种蒸笼,分别能放 3、4 和 5 个包子。当顾客想买 11 个包子时,大叔就会选 2 笼 3 个的再加 1 笼 5 个的(也可能选出 1 笼 3 个的再加 2 笼 4 个的)。
    当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有 3 种蒸笼,分别能放 4、5 和 6 个包子。而顾客想买 7 个包子时,大叔就凑不出来了。
    小明想知道一共有多少种数目是包子大叔凑不出来的。
    第一行包含一个整数 N
    以下 N 行每行包含一个整数 Ai
    https://blog.csdn.net/chenpeixing361/article/details/88422888

public class A8_包子凑数_DP背包 {
	//用于存放包笼存放的包子数目
		static int[] a = new int[100];
		//用于判断1——100*100的正整数能否被凑齐,初始值为假
		static boolean[] dp = new boolean[100*100];
		//求最大公约数函数
		static int gcd(int a,int b) {
			if( b == 0) return a;
			else
				return gcd(b,a%b);
		}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		for( int i=0; i<n; i++ ) {
			a[i] = sc.nextInt();
		}
		int m = a[0];
		//求出多个笼包的最大公约数
		for( int i=1; i<n; i++ ) {
			m = gcd(m,a[i]);
		}
		//如果最大公约数不为1,则输出INF
		if( m != 1) {
			System.out.println("INF");
		}
		//否则利用 完全背包  计算出凑不齐的包子方案数
		/*a[0]=4 ,a[1]=5
		 *       0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 
		 * a[0]  √ × × × √ × × × √ ×  ×  ×  √  ×  ×  ×  √ 
		 * a[1]  √ × × × √ √ × × √ √  √  ×  √  √  √  √  √
		 */		
		else {
			dp[0] = true;//0 肯定可以
			for( int i=0; i<n; i++ ) {
				for( int j=0 ; a[i]+j <100*100; j++) {
					if(dp[j]) {
						dp[a[i]+j] = true;
					}
				}
			}
            
            
            
            
			int count = 0;
			for( int i=0; i<100*100; i++ ) {
				//该包子未被凑齐
				if( dp[i] == false) {
					//这里可以打印出凑不出的包子数目,便于验证
					//System.out.println(i);
					count++;
				}
			}
			System.out.println(count);
		}
	}
}
/*糖果店的老板一共有M种口味的糖果出售。为了方便描述,我们将M种口味编号1~M。
小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是K颗一包整包出售。
幸好糖果包装上注明了其中K颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。
给定N包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。
输入:第一行包含三个整数N、M 和K。
接下来N 行每行K 这整数T1,T2,…,TK,代表一包糖果的口味。
1<=N<=100,1<=M<=20,1<=K<=20,1<=Ti<=M。
输出:一个整数表示答案。如果小明无法品尝所有口味,输出-1。*/
import java.util.*;
//1:无需package
//2: 类名必须Main, 不可修改

public class A09_糖果_快压DP {
 public static void main(String[] args) {
     Scanner scan = new Scanner(System.in);
     int N = scan.nextInt(); // N包糖果
     int M = scan.nextInt(); // M种糖
     int K = scan.nextInt(); // 每包糖K种
     
     int[] sta = new int[N + 1];
     int[] dp = new int[1 << M]; // dp[i] : i这种状态需要几包糖
     
     Arrays.fill(dp, -1);
     dp[0] = 0;
     // 统计每包糖的状态
     for (int i = 1; i <= N; i++) {
         for (int j = 0; j < K; j++) {
             sta[i] |= (1 << (scan.nextInt() - 1)); 
         }
     }
     scan.close();
     for (int i = 0; i < dp.length; i++) {
         // 对于已经存在的状态i,加上第j包糖产生新的结果  --> cur = i | sta[j]
         // 如果这个结果是新结果,或者这个结果已经被组合过但是比通过状态i和第j包糖组合需要的糖果多,更新dp[cur]
         for (int j = 1; j <= N; j++) {
             // 只看状态i已存在的情况
             if (dp[i] == -1) {
                 continue;
             }
             // 产生的新的状态
             int cur = i | sta[j];
             // 符合上述分析的情况,更新dp[cur]
             if (dp[cur] == -1 || dp[i] + 1 < dp[cur]) {
                 dp[cur] = dp[i] + 1;
             }
         }
     }
     System.out.println(dp[(1 << M) - 1]);
 }

6、辗转相除

//求最大公约数    
static int gcd(int a, int b) {
		if (b == 0)
			return a;
		else
			return gcd(b, a % b);

	}

7、并查集

package Blue_10_研究生组;

//oj.ecustacm.c User: 20180861115

import java.io.InputStreamReader;
import java.util.Scanner;

public class A08_修改数组_并查集 {
	static int[] f=new int[2000000];
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        //获取第一行数据
        int n=Integer.parseInt(sc.nextLine());
        int[] data=new int[n];
        
        //初始化f数组
        for (int i = 1; i < f.length; i++) {
            f[i]=i;
        }
        //获取第二行数据,放到数组中
        for (int i = 0; i < n; i++) {
            data[i]=sc.nextInt();
        }
        //并查集使用
        for (int i = 0; i < data.length; i++) {
            int k=find(data[i]);
            data[i]=k;
            f[data[i]]=find(data[i]+1);
        }
        //输出
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i]+" ");
        }            
    }
    //(并查集)
    public static int find(int x) {
        if(x==f[x]) {
            return x;
        }else {
            f[x]=find(f[x]);
            return f[x];
        }
    } 
}

8、乘除逆反

能不能在1至1000000007之间找到一个数,与2021相乘后再除以1000000007后的余数为999999999

A*2021%1000000007=999999999  //求A
// 直接求也可以
for (long i = 0; i < 2022; i++) {
			if((i*1000000007+999999999)%2021==0)
				System.out.println((i*1000000007+999999999)/2021);
		}

9、二分 搜索

(1)blue8-分巧克力

/*9、分巧克力

  • 儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
  • 小明一共有 N块巧克力,其中第 i块是 Hi*Wi 的方格组成的长方形。为了公平起见,
    小明需要从这 N块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:
    形状是正方形,边长是整数;
    大小相同;
    例如一块 6x5 的巧克力可以切出 6 块 2x2 的巧克力或者 2 块 3x3 的巧克力。
    当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
  • 输入描述
    第一行包含两个整数 N,K
    以下 N 行每行包含两个整数 H_i,W_i
    输入保证每位小朋友至少能获得一块 1x1 的巧克力。
  • 输出描述
    输出切出的正方形巧克力最大可能的边长。
  • 输入
    2 10
    6 5
    5 6
  • 输出 2
    */
public class A9_分巧克力_二分 {
	public static void main(String[] args) {
		int n,k;
		int []h=new int[10000];
		int []w=new int[10000];
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		k=sc.nextInt();
		for(int i=0;i<n;i++) {
			h[i]=sc.nextInt();
			w[i]=sc.nextInt();
		}
		
		int l=1;
		int r=100001;//左 右边界值
		int ans=0;
	// 二分法依次试 用找合适或者后继的二分法
		while (l<=r) {
			int mid=(l+r)/2;
			int cnt=0;
			//每块都按照 mid 来切割
			for(int i=0;i<n;i++) {
				cnt+=(h[i]/mid)*(w[i]/mid);//计算所有巧克力的长宽 按长度为mid边长切 结果能切处几个
			}
            
			if(cnt>=k) { //只要符合, L就会+1 所以停止的时候 L大于刚刚好的时候
				l=mid+1;
				ans=mid;
			}
			else {
				r=mid-1;
			}
		}
		System.out.println(ans);
	}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-43RboEwr-1650160924622)(C:\Users\Peng\AppData\Roaming\Typora\typora-user-images\image-20220408113042813.png)]

走廊内部署了 K 台扫地机器人,其中第 i 台在第 Ai 个方格区域中。
已知扫地机器人每分钟可以移动到左右相邻的方格中,并将该区域清扫干净。
请你编写一个程序,计算每台机器人的清扫路线,使得
1.它们最终都返回出发方格,
2.每个方格区域都至少被清扫一遍,
3.从机器人开始行动到最后一台机器人归位花费的时间最少。
注意多台机器人可以同时清扫同一方块区域,它们不会互相影响。
输出最少花费的时间。
在上图所示的例子中,最少花费时间是 6。第一台路线:2-1-2-3-4-3-2,清 扫了 1、2、3、4 号区域。第二台路线 5-6-7-6-5,清扫了 5、6、7。第三台路线 10-9-8-9-10,清扫了 8、9 和 10。
【输入格式】
第一行包含两个整数 N 和 K。 接下来 K 行,每行一个整数 Ai。
【输出格式】
输出一个整数表示答案。
【样例输入】
10 3
5
2
10
【样例输出】 6
【评测用例规模与约定】
对于 30% 的评测用例,1≤ K < N ≤10。 对于 60% 的评测用例,1≤ K < N ≤1000。 对于所有评测用例,1≤ K < N ≤100000,1≤ Ai ≤ N。
思路:挺明显的一个二分题目。我们二分每个机器人的扫地范围,根据数学知识我们可以知道,当每个机器人清扫的面积相差不大时,耗时最少。假设二分的扫地范围是x,对于每一个扫地机器人,我们尽可能让它扫地的右边界大一些,也就是扫过的格子,没有必要绝对不扫。最后看扫地的右边界是否大于等于格子的边界,如果是的话,就说明符合条件,否则就不符合条件
————————————————
版权声明:本文为CSDN博主「时倾-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36932169/article/details/123258303

package Blue_10_研究生组;
/*
 https://www.lanqiao.cn/problems/199/learning/
*/
public class A07_扫地机器人_二分_搜索 {
	
}

三、手算题攻略

https://blog.csdn.net/weixin_43914593/article/details/115795620

(1)python操作大数

for i in range(1,2):
	if(i==0):
		print(i)
        
n = 1001733993063167141
d = 212353
p=891234941
q=1123984201
tmp = (p - 1) * (q - 1)
print(tmp)
for i in range(2,n+1):
    now = i * tmp + 1
    if (now % d == 0):
           print(now // d)   #打印e
           break             #有很多e,求第一个就行了

//快速幂求大数 https://blog.csdn.net/weixin_43914593/article/details/112979612
  def qpow(a,b):
    ret = 1//用res 返回结果
    while b:
        if(b%10==1)://取n的最后一位,判断是否为1
             ret = ret*a
        a = a*a //推算乘积a^2 ->a^4 ->a^6/8
        b>>=1 //b右移动一位,将刚才计算的去除掉
    return ret
 
n = 1001733993063167141
e = 823816093931522017   #试试其他的e
C = 20190324
print(qpow(C,e,n))       #579706994112328949

(2)直接看图做题

(3)找规律

算前部分的值,查看是否有规律

【问题描述】Fibonacci数列是非常著名的数列:
F[1=1,F[2=1,对于i>3,F[=F[i-1+F[i-2]Fibonacci数列有一个特殊的性质,前一项与后一项的比值,F[i]/F[i+1],会趋近于黄金分割。
为了验证这一性质,给定正整数N,请你计算F[N]/F[N+1],并保留8位小数。
【输入格式】一个正整数N(1N2000000000)【输出格式】F[N]/F[N+1]。答案保留8位小数。
【样例输入】2【样例输出】0.50000000

 n超过20的时候,前八位小数已经相同
    if(n<20) {
			for (int i = 0; i <n+1; i++) {
				f[2] = f[0] + f[1];
                f[0] = f[1];
                f[1] = f[2];
			}
			System.out.printf("%.8f",f[0]/f[1]);
		}else {
			System.out.println(0.61803399);
		}


s://blog.csdn.net/weixin_43914593/article/details/112979612
  def qpow(a,b):
    ret = 1//用res 返回结果
    while b:
        if(b%10==1)://取n的最后一位,判断是否为1
             ret = ret*a
        a = a*a //推算乘积a^2 ->a^4 ->a^6/8
        b>>=1 //b右移动一位,将刚才计算的去除掉
    return ret
 
n = 1001733993063167141
e = 823816093931522017   #试试其他的e
C = 20190324
print(qpow(C,e,n))       #579706994112328949

(2)直接看图做题

(3)找规律

算前部分的值,查看是否有规律

【问题描述】Fibonacci数列是非常著名的数列:
F[1=1,F[2=1,对于i>3,F[=F[i-1+F[i-2]Fibonacci数列有一个特殊的性质,前一项与后一项的比值,F[i]/F[i+1],会趋近于黄金分割。
为了验证这一性质,给定正整数N,请你计算F[N]/F[N+1],并保留8位小数。
【输入格式】一个正整数N(1N2000000000)【输出格式】F[N]/F[N+1]。答案保留8位小数。
【样例输入】2【样例输出】0.50000000

 n超过20的时候,前八位小数已经相同
    if(n<20) {
			for (int i = 0; i <n+1; i++) {
				f[2] = f[0] + f[1];
                f[0] = f[1];
                f[1] = f[2];
			}
			System.out.printf("%.8f",f[0]/f[1]);
		}else {
			System.out.println(0.61803399);
		}

你可能感兴趣的:(蓝桥杯,eclipse)