第12届蓝桥杯java A组做题记录

A题:相乘

请添加图片描述

package JAVA12l蓝桥杯;
//求2021的逆元


public class 相乘 {
	static int mod = (int)1e9 + 7;
	public static long qmi(long a,int k,int p)
	{
		long res = 1;
		while(k > 0)
		{
			if(k % 2 == 1) res = res * a % p;
			a = a * a % p;
			k >>= 1;
		}
		return res;
	}
	public static void main(String[] args)
	{
		
		long ans = 999999999 * qmi(2021, mod - 2, mod) % mod;
		System.out.print(ans);
	}
}

B题:直线请添加图片描述

package JAVA12l蓝桥杯;
import java.util.*;
//直线:枚举斜率k和截距b,两者有一个不同的即不同
//如果 k = (y2 - y1)/(x2 - x1)
/// b = (x2 * y1 - x1 *x2)/(x2 - x1)
public class 直线 {
	static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    public static void main(String[] args) {
        Set<String> Set= new TreeSet<>();
        
        for (int x1 = 0; x1 < 20; x1++)
            for (int y1 = 0; y1 < 21; y1++)
                for (int x2 = 0; x2 < 20; x2++)
                    for (int y2 = 0; y2 < 21; y2++)
                        if (x1 != x2) {
                        	int a = y2 - y1;
                            int b = x1 - x2;
                            int c = x2 * y1 - x1 * y2;
                            int gcdn = gcd(a,gcd(b, c));
                            Set.add(a / gcdn +","+b / gcdn +"," + c/gcdn);
                        }

        System.out.println(Set.size() + 20);
    }
}

C题 货物摆放

请添加图片描述

package JAVA12l蓝桥杯;
//枚举因子,写该代码之前计算过了 因子数量130左右
//
public class 货物摆放 {
	static int N = 200,cnt  = 0;
	static long[] factor = new long[N];
	public static void main(String[] args)
	{
		long n = Long.parseLong("2021041820210418");
		for(int i = 1;i <= n / i;i++)
		{
			if(n % i == 0)
			{
				factor[++cnt] = i;
				if(i * i != n) factor[++cnt] = n /i;
				
			}
		}
		long res = 0;
		for(int i = 1;i <= cnt;i++)
			for(int j = 1;j <= cnt; j++)
				if(n % (factor[i] * factor[j]) == 0) res++;
		System.out.print(res);
	}
}

D题 路径

请添加图片描述

package JAVA12l蓝桥杯;

import java.util.*;

// 图的边初始化可以如果小于等于21 i* j /gcd(i,j) else  2e9;
// 最短路问题,用dijkstra 邻接矩阵版
// 最短路每次选一个当前为更新且距离源点最短的点
public class 路径 {
	static int N = 2030,dis[] = new int[N];
	static int[][] g = new int[N][N];
	static boolean[] st = new boolean[N];
	static int dijkstra(int n)
	{
		Arrays.fill(dis,(int) 2e9);
		dis[1] = 0;
		for(int i = 1;i <= n;i++)
		{
			int t = -1;
			for(int j = 1;j <= n;j++)
				if(!st[j] && (t == -1 || dis[t] > dis[j]))
					t = j;
		
			if(t == -1) break;
			st[t] = true;
			for(int j = 1;j <= n;j++)
				if(dis[j] > dis[t] + g[t][j])
					dis[j] = dis[t] + g[t][j];
		}
		return dis[n];
	}
	static int gcd(int a,int b)
	{
		if(b == 0) return a;
		else return gcd(b, a % b);
	}
	
	public static void main(String[] args)
	{
	
		for(int i = 1;i <= 2021;i++)
			for(int j = i + 1;j <= 2021;j++)
				if(j - i <= 21)
					g[i][j] = g[j][i] = i * j / gcd(i, j);
				else g[i][j] = g[j][i] =(int) 2e9;
		
		
		System.out.print(dijkstra(2021));
	}
}

E题 回路计算

请添加图片描述

package JAVA12l蓝桥杯;
import java.util.*;
// dp[i][j] 代表在i号教学楼,访问教学楼状态为j的不同方案
// 包括不包括 i?包括
// dp[i | 1 << k][j] = dp[i][j] += dp[i & ~(1 << (j - 1))][k];
// 最后将所有能dp[1 << 21) - 1]加起来,
public class 回路计算 {
    public static boolean[][] canGo = new boolean[22][22];
    public static long[][] dp = new long[1 << 21][22];
    
    public static void main(String[] args) {
        // 先填表判断哪些楼之间有路
        for (int i = 1; i <= 21; i++) {
            for (int j = 1; j <= 21; j++) {
                if (gcd(i, j) == 1) {
                    canGo[i][j] = true;
                }
            }
        }
        
        dp[1][1] = 1;
        for (int i = 1; i < (1 << 21); i++) {
            for (int j = 1; j <= 21; j++) {
                // j楼在i这种状态里 -- i的第j位是1
                if ((i & (1 << (j - 1))) > 0) {
                    // dp[i][j] += dp[状态i中的j去掉][从那些楼可以到j]
                    // dp[i][j] = 没有走j之前的状态能够走到j的所有可能的和
                    for (int k = 1; k <= 21; k++) {
                        if (canGo[k][j]) {
                            dp[i][j] += dp[i & ~(1 << (j - 1))][k];
                        }
                    }
                }
            }
        }
        
        long res = 0;
        for (int i = 1; i <= 21; i++) {
            res += dp[(1 << 21) - 1][i];
        }
        
        System.out.println(res);
    }
    
    public static int gcd(int a, int b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }
}

F题 最小砝码

请添加图片描述

package JAVA12l蓝桥杯;
// 找规律题 1个砝码表示最多的权重为1 两个最多表示的权重 1 3 
//3个最多表示的权重 为 1 3 9  
//4个最多表示的权重为 1 3 9 27
//可以看出来砝码权重分别为3^i ,用循环求出最少砝码
//3 ,4个如何找,可写程序砝码可表示的数
// 分别用三层循环和四层循环加一个check()函数,枚举当前砝码最多表示的权重为多少选最大的参数

// 这题本质是考三进制,在有减,不取,加的操作下,n 个数位能表示 0~1+3 + 9 +3^n - 1的数
// 二进制在有不取,加的操作下最多能表表示0 ~ 2 ^n - 1的数
import java.util.Scanner;

public class 最小砝码 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.close();
        
        int sum = 0;
        
        for (int i = 0; ; i++) {
            int a = (int) Math.pow(3, i);
            sum += a;
            if (sum >= n) {
                System.out.println(i + 1);
                break;
            }
        }
    }
}

G题 左孩子右兄弟

请添加图片描述

package JAVA12l蓝桥杯;


import java.util.*; 
// dp[u] 代表本子树节点的最大高度 d[u] 代表儿子
// dp[u] = max(dp[son]) + d[u]
// 这里我们可以在dfs 中维护dp[u]
//这里的dp是不是多余的?
//是的,因为每个叶节点只被访问一次

public class 左孩子右兄弟 {
    static int N = (int)1e5 + 10,dp[] = new int[N];
    static int[] h = new int[N], ne = new int[N], e = new int[N], d = new int[N];
    static int idx = 0, ret = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Arrays.fill(h, -1);Arrays.fill(dp, -1);
        int n = sc.nextInt();
        for(int i = 2; i <= n; ++i) {
          int x = sc.nextInt();
          add(x, i); d[x]++;
        }

        System.out.println(dfs(1));
        sc.close();
    }

    public static void add(int a, int b) {
      e[idx] = b; ne[idx] = h[a]; h[a] = idx++;
    }

    public static int dfs(int u) {
      if(dp[u] != -1) return dp[u];
      int ret = 0;
      for(int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        ret = Math.max(ret, dfs(j));
      }
      return dp[u] = ret + d[u];
    } 
}

试题H:异或数列

请添加图片描述

package JAVA12l蓝桥杯;

//从最高位考虑开始开始考虑
//1.若cnt为偶数,则该位所有数亦或的结果为0
//2.若当cnt为奇数时,最后一个1谁拿谁获胜
//2.1若0的个数为偶数(总数为奇数),a先手拿1必胜
//2.2若0的个数位奇数(总数为偶数),a先手拿1则b拿0,a先手拿0则b拿1b后手必胜!
//2.3特别的,需要特判cnt为1的情况先手必胜!
//3.若每一位的1个数都为偶数则平手
// 这里推荐俩题关于异或的 :
// https://www.acwing.com/problem/content/145/ 
// https://atcoder.jp/contests/abc347/tasks/abc347_d

import java.util.Scanner;
public class 异或数列 {
	
	    static final int N = 2_000_005;
	    static int mod = 1_000_000_007;
	    static int n, m, k, S, T;
	    static int[] a = new int[N];

	    public static void main(String[] args) {
	        int tt = sc.nextInt();
	        while (tt-- > 0)
	            solve();
	        sc.close();
	    }

	    static void solve() {
	        n = sc.nextInt();
	        for (int i = 1; i <= n; ++i)
	            a[i] = sc.nextInt();
	        for (int i = 20; i >= 0; --i) {
	            int cnt = 0;
	            for (int j = 1; j <= n; ++j)
	                if (((a[j] >> i) & 1) == 1)
	                    cnt++;
	            if (cnt % 2 == 0)
	                continue;
	            if (n % 2 == 1 || cnt == 1) {
	                System.out.println(1);
	                return;
	            } else {
	                System.out.println(-1);
	                return;
	            }
	        }
	        System.out.println(0);
	    }

	    static Scanner sc = new Scanner(System.in);
}

请添加图片描述
60% 我的评价是见好就收


import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {//这么短的,可惜超时了4个用例
    Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        Integer[] arr=new Integer[n];
        for(int i=1;i<=n;i++) {
            arr[i-1]=i;
        }
        int [][] arr1=new int[m][2];
        for(int i=0;i<m;i++) {
          arr1[i][0]=sc.nextInt();
            arr1[i][1]=sc.nextInt();
        }
        sc.close();
        for(int i=0;i<m;i++) {
            if(arr1[i][0]==0) {
                Arrays.sort(arr,0,arr1[i][1],(a,b)->b-a);//降序
            }else{
                Arrays.sort(arr,arr1[i][1]-1,n);//升序
            }
        }
        for(int i=0;i<n;i++) {
            System.out.print(arr[i]+" ");
        }
        
    }
}

100% 这是写一小时调俩多小时的,考场最好见好就收,目前码力不足以在考场上解决此问题

package JAVA12l蓝桥杯;
import java.util.*;

public class 双向排序 {
    static final int N = 100005;
    static int n, m;
    static int[] sum0 = new int[N << 3];
    static int[] sum1 = new int[N << 3];
    static boolean[] all0 = new boolean[N << 3];
    static boolean[] all1 = new boolean[N << 3];
    static int[] a = new int[N];
    static int pos = 0;

    static void init(int l, int r, int p) {
        if (l == r) {
            sum0[p] = 0;
            sum1[p] = 1;
        } else {
            int mid = (l + r) >> 1, ps = p << 1;
            init(l, mid, ps);
            init(mid + 1, r, ps | 1);
            sum0[p] = sum0[ps] + sum0[ps | 1];
            sum1[p] = sum1[ps] + sum1[ps | 1];
        }
    }

    static void pd(int p) {
        if (all0[p]) {
            sum0[p] += sum1[p];
            sum1[p] = 0;
            all0[p] = false;
            all0[p << 1] = all0[p << 1 | 1] = true;
            all1[p << 1] = all1[p << 1 | 1] = false;
        } else if (all1[p]) {
            sum1[p] += sum0[p];
            sum0[p] = 0;
            all1[p] = false;
            all1[p << 1] = all1[p << 1 | 1] = true;
            all0[p << 1] = all0[p << 1 | 1] = false;
        }
    }

    static int chg1(int num, int l, int r, int p) {
        if (num == 0) return 0;
        pd(p);
        if (num >= sum1[p]) {
            all0[p] = true;
            return num - sum1[p];
        }
        sum1[p] -= num;
        sum0[p] += num;
        int mid = (l + r) >> 1, ps = p << 1;
        return chg1(chg1(num, l, mid, ps), mid + 1, r, ps | 1);
    }

    static int chg2(int num, int l, int r, int p) {
        if (num == 0) return 0;
        pd(p);
        if (num >= sum0[p]) {
            all1[p] = true;
            return num - sum0[p];
        }
        sum0[p] -= num;
        sum1[p] += num;
        int mid = (l + r) >> 1, ps = p << 1;
        return chg2(chg2(num, l, mid, ps), mid + 1, r, ps | 1);
    }

    static void upd(int l, int r, int p) {
        pd(p);
        if (l == r) {
            a[++pos] = sum1[p];
            return;
        }
        int mid = (l + r) >> 1, ps = p << 1;
        upd(l, mid, ps);
        upd(mid + 1, r, ps | 1);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        init(1, n, 1);
        int mid = 1;
        while (m-- > 0) {
            int p = scanner.nextInt();
            int q = scanner.nextInt();
            if (p == 0) {
                if (q >= mid) {
                    chg1(q - mid + 1, 1, n, 1);
                    mid = q + 1;
                }
            } else {
                if (q < mid) {
                    chg2(mid - q, 1, n, 1);
                    mid = q;
                }
            }
        }
        upd(1, n, 1);
        for (int i = n; i >= 1; --i) {
            if (a[i] == 0) System.out.print(i + " ");
        }
        for (int i = 1; i <= n; ++i) {
            if (a[i] != 0) System.out.print(i + " ");
        }
    }
}

请添加图片描述

占位

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值