蓝桥杯2020.07省赛B组 Java

整除序列(大数模拟)

有一个序列,序列的第一个数是 n,后面的每个数是前一个数整除 2,请输出这个序列中值为正数的项。

输入格式
输入一行包含一个整数 n。

输出格式
输出一行,包含多个整数,相邻的整数之间用一个空格分隔,表示答案。

数据范围
1≤n≤1018
输入样例:
20
输出样例:
20 10 5 2 1

import java.util.*;
import java.math.BigInteger;
class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        BigInteger n = new BigInteger(s);
        BigInteger m = new BigInteger("2");
        while(!n.equals(BigInteger.ZERO)){
            System.out.print(n+" ");
            n = n.divide(m);
        }
    }
}

解码(遍历枚举)

小明有一串很长的英文字母,可能包含大写和小写。

在这串字母中,有很多连续的是重复的。

小明想了一个办法将这串字母表达得更短:将连续的几个相同字母写成字母 + 出现次数的形式。

例如,连续的 5 个 a,即 aaaaa,小明可以简写成 a5(也可能简写成 a4a、aa3a 等)。

对于这个例子:HHHellllloo,小明可以简写成 H3el5o2。

为了方便表达,小明不会将连续的超过 9 个相同的字符写成简写的形式。

现在给出简写后的字符串,请帮助小明还原成原来的串。

输入格式
输入一行包含一个字符串。

输出格式
输出一个字符串,表示还原后的串。

数据范围
输入字符串由大小写英文字母和数字组成,长度不超过 100。
请注意原来的串长度可能超过 100。

输入样例:
H3el5o2
输出样例:
HHHellllloo

import java.util.*;
class Main{
    public static void main(String []args){
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < s.length(); i++){
            if(Character.isDigit(s.charAt(i))){
                for(int j = 1; j < (int)(s.charAt(i)-'0');j++){
                    sb.append(s.charAt(i-1));
                }
            }else{
                sb.append(s.charAt(i));
            }
        }
        System.out.println(sb.toString());
    }
}

走方格(简单的dp)

在平面上有一些二维的点阵。

这些点的编号就像二维数组的编号一样,从上到下依次为第 1 至第 n 行,从左到右依次为第 1 至第 m 列,每一个点可以用行号和列号来表示。

现在有个人站在第 1 行第 1 列,要走到第 n 行第 m 列。

只能向右或者向下走。

注意,如果行号和列数都是偶数,不能走入这一格中。

问有多少种方案。

输入格式
输入一行包含两个整数 n,m。

输出格式
输出一个整数,表示答案。

数据范围
1≤n,m≤30
输入样例1:
3 4
输出样例1:
2
输入样例2:
6 6
输出样例2:
0

这题是一个简答的dp问题,从题目可以看出,每个方块只能从它的上面和左面到达,并且行数和列数都不能是偶数,所以经过n*m的循环后就可以找到值了。

import java.util.*;
class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        
        int[][] dp = new int[n+1][m+1];
        dp[0][1] = 1;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(i%2==0&&j%2==0){
                    dp[i][j] = 0;
                    continue;
                }
                dp[i][j] = dp[i][j-1]+dp[i-1][j];
                
            }
        }
        System.out.println(dp[n][m]);
    }
}

整数拼接

给定一个长度为 n 的数组 A1,A2,⋅⋅⋅,An。

你可以从中选出两个数 Ai 和 Aj(i 不等于 j),然后将 Ai 和 Aj 一前一后拼成一个新的整数。

例如 12 和 345 可以拼成 12345 或 34512。

注意交换 Ai 和 Aj 的顺序总是被视为 2 种拼法,即便是 Ai=Aj 时。

请你计算有多少种拼法满足拼出的整数是 K 的倍数。

输入格式
第一行包含 2 个整数 n 和 K。

第二行包含 n 个整数 A1,A2,⋅⋅⋅,An。

输出格式
一个整数代表答案。

数据范围
1≤n≤105,
1≤K≤105,
1≤Ai≤109
输入样例:
4 2
1 2 3 4
输出样例:
6

import java.util.Scanner;

public class Main {
    static int N = (int) 1e5 + 10;
    static int[][] s = new int[11][N];
    static int[] a = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }
        for (int i = 0; i < n; i++) {
            long t = a[i] % m;
            for (int j = 0; j < 11; j++) {
                s[j][(int) t]++;
                t = t * 10 % m;
            }
        }
        long res = 0;
        for (int i = 0; i < n; i++) {
            long t = a[i] % m;
            int len = String.valueOf(a[i]).length();
            res += s[len][(int) ((m - t) % m)];
            long r = t;
            while (len-- != 0 ){
                r = r * 10 % m;
            } //求a[j]的余数,同上面的预处理求法一样
            if (r == (m - t) % m) {
                res--;
            }
        }
        System.out.println(res);
    }
}

网络分析

小明正在做一个网络实验。

他设置了 n 台电脑,称为节点,用于收发和存储数据。

初始时,所有节点都是独立的,不存在任何连接。

小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通信了。

两个节点如果存在网线连接,称为相邻。

小明有时会测试当时的网络,他会在某个节点发送一条信息,信息会发送到每个相邻的节点,之后这些节点又会转发到自己相邻的节点,直到所有直接或间接相邻的节点都收到了信息。

所有发送和接收的节点都会将信息存储下来。

一条信息只存储一次。

给出小明连接和测试的过程,请计算出每个节点存储信息的大小。

输入格式
输入的第一行包含两个整数 n,m,分别表示节点数量和操作数量。

节点从 1 至 n 编号。

接下来 m 行,每行三个整数,表示一个操作。

如果操作为 1 a b,表示将节点 a 和节点 b 通过网线连接起来。当 a = b 时,表示连接了一个自环,对网络没有实质影响。
如果操作为 2 p t,表示在节点 p 上发送一条大小为 t 的信息。
输出格式
输出一行,包含 n 个整数,相邻整数之间用一个空格分割,依次表示进行完上述操作后节点 1 至节点 n 上存储信息的大小。

数据范围
1≤n≤10000,
1≤m≤105,
1≤t≤100
输入样例1:
4 8
1 1 2
2 1 10
2 3 5
1 4 1
2 2 2
1 1 2
1 2 4
2 2 1
输出样例1:
13 13 5 3




import java.util.Scanner;

public class Main {
    static int N = 10010;
    static int n, m;
    static int[] p = new int[N];
    static int[] d = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();

        for (int i = 1; i <= n; i++) {
            p[i] = i;
        }
        while (m-- != 0) {
            int t = sc.nextInt();
            int a = sc.nextInt();
            int b = sc.nextInt();
            if (t == 1) {
                a = find(a);
                b = find(b);
                if (a != b) {
                    d[a] -= d[b];
                    p[a] = b;
                }
            } else {
                a = find(a);
                d[a] += b;
            }

        }
        for (int i = 1; i <= n; i++) {
            if (i == find(i)) {
                System.out.print(d[i]+" ");
            } else {
                System.out.print(d[i] + d[find(i)]+" ");
            }
        }

    }

    static int find(int x) {
        if (p[x] == x || p[p[x]] == p[x]) {
            return p[x];
        }
        int r = find(p[x]);
        d[x] += d[p[x]];
        p[x] = r;
        return r;
    }
}

超级胶水

小明有 n 颗石子,按顺序摆成一排。

他准备用胶水将这些石子粘在一起。

每颗石子有自己的重量,如果将两颗石子粘在一起,将合并成一颗新的石子,重量是这两颗石子的重量之和。

为了保证石子粘贴牢固,粘贴两颗石子所需要的胶水与两颗石子的重量乘积成正比,本题不考虑物理单位,认为所需要的胶水在数值上等于两颗石子重量的乘积。

每次合并,小明只能合并位置相邻的两颗石子,并将合并出的新石子放在原来的位置。

现在,小明想用最少的胶水将所有石子粘在一起,请帮助小明计算最少需要多少胶水。

输入格式
输入的第一行包含一个整数 n,表示初始时的石子数量。

第二行包含 n 个整数 w1,w2,…,wn,依次表示每颗石子的重量。

输出格式
一个整数表示答案。

数据范围
1≤n≤105,
1≤wi≤1000
输入样例1:
3
3 4 5
输出样例1:
47
输入样例2:
8
1 5 2 6 3 7 4 8
输出样例2:
546



import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long[] dp = new long[n+1];
        long res = 0;
        for(int i=1;i<=n;i++){
            int a = sc.nextInt();
            dp[i] = dp[i-1]+a;
            res += dp[i-1]*a;
        }
        System.out.println(res);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值