目录
被蓝桥杯整的焦虑死了,我要复习复习!!!
1.二维前缀和
import java.util.Scanner;
public class 统计子矩阵 {
static int N=510;
static int[][]g=new int[N][N];
static int[][]s=new int[N][N];
static int res=0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int K = sc.nextInt();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
g[i][j] = sc.nextInt();
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+g[i][j];
}
}
//枚举子矩阵
//矩阵左上角
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=i;k<=n;k++){
for(int l=j;l<=m;l++){
int sum=s[k][l]-s[k][j-1]-s[i-1][l]+s[i-1][j-1];
if(sum<=K){
res++;
}
}
}
}
}
System.out.println(res);
}
}
2.BigIntenger常用方法
快速幂取模:
BigInteger a=new BigInteger("2");
BigInteger b=new BigInteger("6");
BigInteger p=new BigInteger("10");
BigInteger bigInteger = a.modPow( b,p);
System.out.println(bigInteger);
最大公约数,最小公倍数数据较大的时候(高精度)
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
BigInteger a=new BigInteger("1");
BigInteger b=new BigInteger("2");
BigInteger c=new BigInteger("1");
for(int i=2;i<=n;i++) {
a=lcm(a,b);
b=b.add(c);
}
System.out.println(a);
}
public static BigInteger lcm(BigInteger a,BigInteger b) {
return a.multiply(b).divide(a.gcd(b));
}
}
3.差分
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
long[]a=new long[n+1];
long[]s=new long[n+1];
long[]cnt=new long[n+1];
long[]C=new long[n+2];
for(int i=1;i<=n;i++) {
a[i]=sc.nextLong();
s[i]=s[i-1]+a[i];
}
long m=sc.nextLong();
long and=0;
while(m--!=0) {
long l=sc.nextLong();
long r=sc.nextLong();
and+=s[(int) r]-s[(int) (l-1)];
C[(int) l]+=1;
C[(int) (r+1)]-=1;
}
for(int i=1;i<=n;i++) {
cnt[i]=cnt[i-1]+C[i];
}
long ans=0;
Arrays.sort(cnt,1,n+1);
Arrays.sort(a,1,n+1);
for(int i=1;i<=n;i++) {
ans+=a[i]*cnt[i];
}
System.out.println(ans-and);
}
}
4.DFS
import java.util.Scanner;
public class Main {
static int N=20;
static int[]a=new int[N];
static int n;
static boolean flag=false;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
for(int i=1;i<=n;i++) {
a[i]=sc.nextInt();
}
dfs(1,0);
if(flag) {
System.out.println("YES");
}else {
System.out.println("NO");
}
}
public static void dfs(int u,int res) {
if(u>n) {
if(res==0||res%360==0) {
flag=true;
}
return ;
}
dfs(u+1,res+a[u]);
dfs(u+1,res-a[u]);
}
}
5.01背包
import java.util.Scanner;
public class Main {
static int N=1000010;
static int[]p=new int[N];
public static void main(String[] args) {
int ans=0;
Scanner sc=new Scanner(System.in);
int m=sc.nextInt();
int n=sc.nextInt();
for(int i=1;i<=m*n;i++) {
p[i]=i;
}
int k=sc.nextInt();
while(k--!=0) {
int a=sc.nextInt();
int b=sc.nextInt();
p[find(a)]=find(b);
}
for(int i=1;i<=m*n;i++) {
if(p[i]==i) {
ans++;
}
}
System.out.println(ans);
}
public static int find(int x) {
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
}
6.并查集
import java.util.Scanner;
public class Main {
static int N=1000010;
static int[]p=new int[N];
public static void main(String[] args) {
int ans=0;
Scanner sc=new Scanner(System.in);
int m=sc.nextInt();
int n=sc.nextInt();
for(int i=1;i<=m*n;i++) {
p[i]=i;
}
int k=sc.nextInt();
while(k--!=0) {
int a=sc.nextInt();
int b=sc.nextInt();
p[find(a)]=find(b);
}
for(int i=1;i<=m*n;i++) {
if(p[i]==i) {
ans++;
}
}
System.out.println(ans);
}
public static int find(int x) {
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
}
7.BFS
有一个整数 A=2021,每一次,可以将这个数加 1 、减 1 或除以 2,其中除以 2 必须在数是偶数的时候才允许。
例如,2021 经过一次操作可以变成 2020、2022。
再如,2022 经过一次操作可以变成 2021、2023 或 1011。
请问,2021 最少经过多少次操作可以变成 1。
public class Main3 {
public static void main(String[] args) {
//数组开个10000完全够用了
boolean[] visit=new boolean[10000];
Queue<Integer> queue=new LinkedList<>();
queue.offer(2021);
visit[2021]=true;
int time=0;
while(!queue.isEmpty()) {
int size=queue.size();
while(size-->0) {
int curr=queue.poll();
//判断curr如果是1则直接输出time就是我们的答案
if(curr==1) {
System.out.println(time);//14
return;
}
if(!visit[curr+1]) {
visit[curr+1]=true;
queue.offer(curr+1);
}
if(!visit[curr-1]) {
visit[curr-1]=true;
queue.offer(curr-1);
}
//一定要记住,只有偶数才可以选择除以2的操作
if(curr%2==0&&!visit[curr/2]) {
visit[curr/2]=true;
queue.offer(curr/2);
}
}
time++;
}
}
}
8.最短路模板
import java.util.*;
public class Main{
static int N = 510,n,m, max = 0x3f3f3f3f;
static int[][] g = new int[N][N];//存每个点之间的距离
static int[] dist = new int[N];//存每个点到起点之间的距离
static boolean[] st = new boolean[N];//存已经确定了最短距离的点
public static int dijkstra(){
Arrays.fill(dist,max);//将dist数组一开始赋值成较大的数
dist[1] = 0; //首先第一个点是零
//从0开始,遍历n次,一次可以确定一个最小值
for(int i = 0 ; i < n ; i ++ ){
int t = -1; //t这个变量,准备来说就是转折用的
for(int j = 1 ; j <= n ; j ++ ){
/***
* 因为数字是大于1的,所以从1开始遍历寻找每个数
* 如果s集合中没有这个数
* 并且t == -1,表示刚开始 或者 后面的数比我心找的数距离起点的距离短
* 然后将j 的值赋值给 t
***/
if(!st[j] && (t == -1 || dist[j] < dist[t])){
t = j;
}
}
st[t] = true;//表示这个数是已经找到了确定了最短距离的点
//用已经确认的最短距离的点来更新后面的点
//就是用1到t的距离加上t到j的距离来更新从1到j的长度
for(int j = 1 ; j <= n ; j ++ ){
//
dist[j] = Math.min(dist[j],dist[t] + g[t][j]);
}
}
//如果最后n的长度没有改变,输出-1,没有找到;否则输出最短路n
if(dist[n] == max) return -1;
else return dist[n];
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
//将他们每个点一开始赋值成一个较大的值
for(int i = 1 ; i <= n ; i ++ ){
Arrays.fill(g[i],max);
}
while(m -- > 0){
int a = scan.nextInt();
int b = scan.nextInt();
int c = scan.nextInt();
g[a][b] = Math.min(g[a][b],c);//这个因为可能存在重边,所以泽出最短的
}
int res = dijkstra();
System.out.println(res);
}
}
9.分解质因数
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
long n=sc.nextLong();
long res=0;
for(long i=2;i<=n/i;i++){
if(n%i==0){
while(n%i==0){
n/=i;
}
res++;
}
}
//39===3
if(n>1) res++;
System.out.println(res);
}
}
10.两个小结论:
已知a,b为质数,则不能由a,b凑出来的最大的数是(a-1)(b-1)-1 ;
一段子数组在包含一段连续的自然数时,会有什么性质?设区间[ L , R ][L,R]的值域为[ m i n , m a x ] ,不难发现如果该区间是一段连续自然数时,将会满足:
max−min=j-i;
今天就复习到这里吧,回去吃我的塔斯丁去啦!