## 蓝桥基础 ### 离散化 ``` package LQ_10; import java.util.*; public class EXE { public static void main(String[] args) { Scanner scan=new Scanner (System.in); int n=scan.nextInt(); int[] arr=new int[n]; int[] a=new int[n]; for(int i=0;iset=new HashSet<>(); Arrays.sort(a); Mapmap=new HashMap<>(); for(int i=0;i0){ cnt+=n%7; n/=7; } System.out.println(cnt); } } ``` ## 常识题 **本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。** 小蓝的IP地址为 `192.168.*.21`,其中 `*` 是一个数字,请问这个数字最大可能是多少? ## 高精度 ### 题目描述 计算 A×B*A*×*B* 。 ### 输入描述 每一行将包含两个整数 A*A* 和 B*B*。备注:每个整数的长度不能超过 1000010000。 ### 输出描述 输出 A×B*A*×*B* 。 ### 输入输出样例 #### 示例 1 ### 题目描述 计算 A×B*A*×*B* 。 ### 输入描述 每一行将包含两个整数 A*A* 和 B*B*。备注:每个整数的长度不能超过 1000010000。 ### 输出描述 输出 A×B ```txt 1000 2 ``` ```txt 2000 ``` ```java import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改 import java.math.BigInteger;***注意导包 public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); while(scan.hasNext()) { BigInteger a=scan.nextBigInteger(); BigInteger b=scan.nextBigInteger(); System.out.println(a.multiply(b)); } } } ``` ============================================================================================================================================================================================================================================================================================================================ ## 双指针 1372 ```java package LQ_10; import java.util.*; public class LQ1372 { public static void main(String [] args) { Scanner scan = new Scanner(System.in); int n=scan.nextInt();//n个数 int s=scan.nextInt();//s 目标常数 int ans=Integer.MAX_VALUE;//表示长度 int sum=0;//表示和 int [] arr=new int[n]; for(int i=0;i=s 那么就是sum=-arr[j] j++这样 i在前面扩大长度 j在后面缩小长度 当i=0){ System.out.println(a); } else{ System.out.println(-a); } } } ``` ## 排序 ### 冒泡 把最大的冒泡到前面去 ```java int []arr= {5,8,4,4,6,7,4,8}; for (int i = arr.length - 1; i > 0; i--) { // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (arr[j] > arr[j + 1]) { // 交换 arr[j] 与 arr[j + 1] int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } for(int i:arr) { System.out.printf(i+" "); } 时间复杂度O N^2 ``` ### 选择 选择最小的与前面的交换 ```java int []arr= {3,8,4,4,6,7,4,8,9,1,1,1,5,2,7,8,15}; for(int i=0;i0&&nums[j]>base) { nums[j+1]=nums[j]; j--; } nums[j+1]=base; } for(int i:nums) { System.out.printf(i+" "); } } } ``` ### 快排 ```java package LQ_10; public class EXE { public static void main(String[] args) { int[] nums = { 3, 8, 4, 4, 6, 7, 4, 8, 9, 1, 1, 1, 5, 2, 7, 8, 15 }; quickSort(nums,0,nums.length-1); for (int i : nums) { System.out.printf(i + " "); } } public static void swap(int[] nums, int i, int j) { int t = nums[i]; nums[i] = nums[j]; nums[j] = t; } public static void quickSort(int []nums,int left,int right) { if(left>right)return;//左边的数等于右边的数 就是说只有一个数了 那还排什么 int pivot=partition(nums,left,right);//找中枢点 quickSort(nums,left,pivot-1); quickSort(nums,pivot+1,right); } public static int partition(int []nums,int left,int right) { int i=left,j=right; while(i=nums[left])j--; while(i0) { str1.append(a%x); a/=x; } return str1.reverse().toString(); } ``` ## 贪心 ```java package LQ_10; import java.util.*; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int n=scan.nextInt(); List lt=new ArrayList(); for(int i=0;i1) { int a=lt.get(0); int b=lt.get(1); sum+=a+b; lt.remove(0); lt.remove(0); lt.add(a+b); Collections.sort(lt); } System.out.print(sum); scan.close(); } } ``` ![image-20241030223825354](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241030223825354.png) # 系统学习 ## 循环 ### 进制转换 ```java import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int a=scan.nextInt(); int out=0; int pow=1; while(a>0){ int c=a%10; a/=10; out+=c*pow; pow*=9; } System.out.println(out); scan.close(); } } ``` ### 枚举法求最大公约数 ```java 设a, b是两个整数,如果d能整除a且d能整除b,那么,d就称为是a和b的公约数。a和b的公约数中最大的整数称为a和b的最大公约数。 输入两个正整数a和b,求它们的最大公约数。 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int a = scan.nextInt(), b = scan.nextInt(); int min= Math.min(a, b); for(int i=min;i>=1;i--){ if(a%i==0 && b%i==0){ System.out.println(i); break; } } scan.close(); } } 递归大法 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改 public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int a = sc.nextInt(); int b = sc.nextInt(); sc.close(); System.out.println(gcd(a,b)); } public static int gcd(int a,int b) { return b == 0 ? a : gcd(b,a%b); } } ``` ## 数组与字符串 ### 冒泡排序 ```java import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int n=scan.nextInt(); int arr[]=new int[n]; for(int i=0;iarr[j+1]){ int temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } for(int i=0;i= x)//如果被定义为信赖的为1 arr[i]=1; else arr[i]=0; brr[i]=brr[i-1]+arr[i];//前缀和 } for(int i=1;i<=q;i++){ int l= in.nextInt(),r= in.nextInt(); System.out.println(brr[r]-brr[l-1]); } in.close(); } } ``` ### 二维差分数 给定一个 大小的矩阵 。 给定 组查询,每次查询为给定 4 个正整数 ,你需要输出 的值。 第一行输入 3 个正整数 。 接下来 行每行输入 个整数,表示 。 接下来 行,每行输入 4 个正整数 对于每次查询,输出一个整数,表示查询的子矩阵的和。 ```plaintext 3 4 3 1 7 2 4 3 6 2 8 2 1 2 3 1 1 2 2 2 1 3 4 1 3 3 4 ``` #### 样例输出 ```plaintext 17 27 21 ``` ```java import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int n = scan.nextInt(); int m = scan.nextInt(); int q = scan.nextInt(); int[][] sum = new int[n + 1][m + 1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + scan.nextInt(); } } while (q-- > 0) { int x1 = scan.nextInt(); int y1 = scan.nextInt(); int x2 = scan.nextInt(); int y2 = scan.nextInt(); int result = sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1]; System.out.println(result); } scan.close(); } } ``` ## 单调队列 ### 滑动窗口问题 ```java import java.util.ArrayDeque; import java.util.Deque; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] num = new int[10]; int n, k; n = sc.nextInt(); k = sc.nextInt(); int[] ans = new int[n - k + 1]; Deque q = new ArrayDeque(); for (int i = 0; i < n; i++) { while (!q.isEmpty() && num[i] > num[q.peekLast()]) { q.pollLast(); } q.addLast(i); if (i - q.getFirst() >= k) {//如果队列头部的元素已经不在滑动窗口内,则将其移除 q.pollFirst(); } if (i >= k - 1) ans[i - k + 1] = num[q.getFirst()];//记录当前滑动窗口的最大值 } } } ``` ## 位运算 ### 相或为k(2星) #### 问题描述 给定你n个非负整数a[i],你是否可以从中选出一些数进行或运算使得值为k,若可以,则输出Yes,若不可以,则输出No。 或运算:二进制位1|1 = 1, 1|0 = 1, 0|0 = 0。 #### 输入格式 第一行一个t代表数据组数。 每组数组第一行二个整数n, k。 每组数据第二行n个数a[i]。 #### 输出格式 输出t行,为符合题目要求的Yes或No。 #### 样例输入 #### 1 4 6 1 2 3 4 #### 样例输出 Yes ```java import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改 public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int t = sc.nextInt(); while(t-->0) { int n = sc.nextInt(); int k= sc.nextInt(); int ans=0; for(int i=0;i 0) { //求出能有几个会被5整除的 因为在阶乘中5有1个5 25有2个5 所以说通过循环 来判断这个数究竟能被几个5整除 num += x / 5; x /= 5; } return num; } public static void main(String[] args) { Scanner scan = new Scanner(System.in); long n = scan.nextLong(); long left = 0L; long right = (long) 1e18 ; while (left < right) { long mid = (left + right) / 2; if(n<=cale(mid)){ right = mid ; } else{ left = mid+1 ; } } if(cale(right)!=n){ System.out.println(-1); } else{ System.out.println(right); } scan.close(); } } ``` ## 莫名其妙中间省略了好多 ## 背包01dp ```java n = in.nextInt(); m = in.nextInt(); int []v=new int[n+1];//价值 int []w=new int[n+1];//体积 for(int i=0;i=w[i]){ dp[i][j]=Math.max(dp[i][j],dp[i-1][j-w[i]]+v[i]); } } //////////////////////////////// //////////////////////////////////////////////////////////////// 一维优化 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n, m; n = in.nextInt(); m = in.nextInt(); int[] v = new int[n + 1]; int[] w = new int[n + 1]; for (int i = 0; i < n; i++) { v[i] = in.nextInt(); w[i] = in.nextInt(); } int[] dp = new int[m + 1]; for (int i = 0; i < n; i++) { for (int j = m; j >= w[i]; j--) {//这是从后往前来的 只能这样 因为只有这样 不然从前往后的话就会多加 dp[j] = Math.max(dp[j], dp[ j - w[i] ] + v[i]); /* 是这样的 因为啊 这个dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]); 需要等价于 dp[i][j]=dp[i-1][j]; if(j>=w[i]){ dp[i][j]=Math.max(dp[i][j],dp[i-1][j-w[i]]+v[i]); dp[j] = Math.max(dp[j] 是没有错的Math.max(dp[j] 是上一个的 其实就是等价于dp[i][j]=Math.max(dp[i][j] 可以这么认为 因为此时左边的dp[j]还没有被算出来 而右边的dp[j]是上一个dp[i-1][j]的 已经被算出来的 */ } } in.close(); } } ``` ## 完全背包 ```java n = in.nextInt(); m = in.nextInt(); int []v=new int[n+1];//价值 int []w=new int[n+1];//体积 for(int i=0;i=w[i]){ dp[i][j]=Math.max(dp[i][j],dp[i][j-w[i]]+v[i]); } } //注意这个 dp[i][j]=Math.max(dp[i][j],dp[i][j-w[i]]+v[i]); 其实完全背包和01背包差不多 都是依赖上一层的来推出下一层 只不过完全背包可以对同一个物品多次拿去 所以它的上一层就可能是自己发展过来的 所以就是dp[i][j-w[i]]+v[i] //////////////////////////////////////////////////////////////////////////////////////////////// 一维优化 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n, m; n = in.nextInt(); m = in.nextInt(); int[] v = new int[n + 1]; int[] w = new int[n + 1]; for (int i = 0; i < n; i++) { v[i] = in.nextInt(); w[i] = in.nextInt(); } int[] dp = new int[m + 1]; for (int i = 0; i < n; i++) { for (int j =w[i]; j<=m; j++) {//这是从前往后来的 所以说就是可以直接从w[i]到m 跟上面的反着记就好了 dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]); } } in.close(); } } ``` ## 多重背包 ```java 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(),m=sc.nextInt(); int v[]=new int[n+1]; int w[]=new int[n+1]; int c[]=new int[n+1]; int dp[]=new int[m+1]; for (int i = 1; i <= n; i++) { v[i]=sc.nextInt(); w[i]=sc.nextInt(); c[i]= sc.nextInt(); } for (int i = 1; i <= n; i++) { for (int j = m; j >=v[i]; j--) { for (int k = 0; k*v[i]<=j&&k<=c[i] ; k++) {//不仅选的次数要关注容量 也要关注本身的限制 dp[j]=Math.max(dp[j],dp[j-k*v[i]]+k*w[i]); } } } System.out.println(dp[m]); } } O(N*M*K)比较大 只能支持100的数值 ``` ## 区间DP ```JAVA 题目描述 在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。例如:输入{1,2,3,4,5},输出33。【3+6+9+15=33】 输入 本题应该处理到文件尾,每组输入包括两行,第一行为石子堆的个数n,第二行则为每堆石子的个数。 输出 输出最小花费。 样例输入 5 1 2 3 4 5 样例输出 33 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改 public class Main { static int N = 300; static int[] s = new int[N];//前缀和 static int[][] dp = new int[N][N];//i j 这个数组的每一位ij 都代表的是i->j 的最少的花费 public static void main(String[] args) { Scanner in = new Scanner(System.in); int n=in.nextInt(); for(int i=1;i<=n;i++){ s[i]=in.nextInt()+s[i-1]; } for(int len=2;len<=n;len++){ for(int l=1;len+l-1<=n;l++){ int r =len+l-1; dp[l][r]=Integer.MAX_VALUE; for(int k = l; k< r; k++){ dp[l][r]=Math.min(dp[l][r],dp[l][k]+dp[k+1][r]+s[r]-s[l-1]); } } } System.out.println(dp[1][n]); } } ```