2020 蓝桥杯大学 B 组模拟赛(五)

1、数字操作

答案:996

算法分析

直接模拟

Java 代码

public class Main {
    
    public static void main(String[] args) {
        int n = 998244353;
        int k = 29;
        while(k -- > 0)
        {
            if(n % 10 == 0) n /= 10;
            else n -= 1;
        }
        System.out.println(n);
    }
}

2、字符串操作

算法分析

说白了就是贪心的思想,尽可能的往大的字母靠,计算出每个字母有多少个,若当前字母有超过两个

Java 代码

public class Main {
    static int N = 27;
    static int[] cnt = new int[N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        char[] g = scan.next().toCharArray();
        for(int i = 0;i < g.length;i ++)
        {
            cnt[g[i] - 'a'] ++;
        }
        for(int i = 0;i < 25;i ++)
        {
            if(cnt[i] >= 2)
            {
                cnt[i + 1] += cnt[i] / 2;
                cnt[i] %= 2;
            }
        }
        for(int i = 25;i >= 0;i --)
        {
            for(int j = cnt[i];j > 0;j --)
                System.out.print((char)(i + 'a'));
        }
    }
}

3、煎牛扒

答案:499122180

算法分析

等价于一次能煎20个,一次需要10分钟

Java 代码

public static void main(String[] args){
        long n = 998244353;
        long cnt = 0;
        if(n % 20 == 0) cnt = n / 20;
        else cnt = n / 20 + 1;
        System.out.println(cnt * 10);
    }

4、数列求值

答案:959741112

算法分析

模拟,注意需要开longlong

Java代码

static int N = 20200202;
    static long[] a = new long[N + 10];
    static int mod = 998244353;
    public static void main(String[] args){
        a[1] = 1;
        a[2] = 1;
        a[3] = 1;
        for(int i = 4;i <= N;i ++)
        {
            a[i] = (7 * a[i - 1] + 10 * a[i - 2] + 6 * a[i - 3]) % mod;
        }
        System.out.println(a[N]);
    }

5、卡片游戏

答案

算法分析

爆搜所有的情况,当君选了左边或者右边时,妹都能通过贪心的算法固定选一个,在给定的区间中,dfs(start,end,v)表示搜索到当前区间[start,end],君比妹多v的价值

  • 当君选了a[start]
    a[start + 1] >= a[end],则妹就会选a[start + 1],区间缩到[start + 2,end],否则选择a[end],区间缩到[start + 1,end - 1]
  • 当君选了a[end]
    a[start] >= a[end - 1],则妹就会选a[start],区间缩到[start + 1,end - 1],否则选择a[end - 1],区间缩到[start,end - 2]
    这样子做的跑的次数是2^50,大概是10^15次,1秒跑10^8次左右,基本要跑几个小时的,因此需要进行优化,由上面的递归过程可以发现,当区间固定时,该区间得到的差值一定是固定的,因此可以用记忆化搜索把当前区间的答案存储下来

Java 代码(爆搜版)

import java.util.Scanner;

public class Main {
    static int N = 110;
    static int[] a = new int[N];
    static int ans = Integer.MIN_VALUE;
    static void dfs(int start,int end,int v)
    {
        if(start > end)
        {
            ans = Math.max(ans, v);
            return;
        }
        //拿start
        if(a[start + 1] >= a[end]) dfs(start + 2,end,v + a[start] - a[start + 1]);
        else dfs(start + 1,end - 1,v + a[start] - a[end]);
        //拿end
        if(a[start] >= a[end - 1]) dfs(start + 1,end - 1,v + a[end] - a[start]);
        else dfs(start,end - 2,v + a[end] - a[end - 1]);
        
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        for(int i = 1;i <= n;i ++) a[i] = scan.nextInt();
        dfs(1,n,0);
        System.out.println(ans);
    }
}

Java 代码(记忆化搜索版)

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int N = 110;
    static int[] a = new int[N];
    static int[][] f = new int[N][N];
    static int dfs(int start,int end)
    {
        if(start > end) return 0;
        if(f[start][end] != -1) return f[start][end];
        //拿start
        f[start][end] = -0x3f3f3f3f;
        if(a[start + 1] >= a[end]) 
            f[start][end] = Math.max(f[start][end],dfs(start + 2,end) + a[start] - a[start + 1]);
        else 
            f[start][end] = Math.max(f[start][end],dfs(start + 1,end - 1) + a[start] - a[end]);
        //拿end
        if(a[start] >= a[end - 1])
            f[start][end] = Math.max(f[start][end], dfs(start + 1,end - 1) + a[end] - a[start]);
        else 
            f[start][end] = Math.max(f[start][end], dfs(start,end - 2) + a[end] - a[end - 1]);
        return f[start][end];
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        for(int i = 1;i <= n;i ++) a[i] = scan.nextInt();
        for(int i = 0;i <= n;i ++) Arrays.fill(f[i], -1);
        System.out.println(dfs(1,n));
    }
}

6、打字

算法分析

用数组模拟栈或者栈模拟操作
Space:加一个'#'代表空格,最后输出的时候判断即可
CapsLock:切换大小写,statefalse表示小写,true表示大写
Backspace:删除元素
字母:需要判断state是表示小写还是大写,再添加到数组中

时间复杂度O(n)

Java 代码

import java.util.Scanner;

public class Main {
    static int N = 100010;
    static char[] ans = new char[N];
    static int k = 0;
    static boolean state = false;//一开始是小写
    public static void main(String[] args){
       Scanner scan = new Scanner(System.in);
       int n = scan.nextInt();
       while(n -- > 0)
       {
           String op = scan.next();
           if(op.equals("Space"))
           {
               ans[++ k] = '#';
           }
           else if(op.equals("CapsLock"))
           {
              state = state ? false : true;
           }
           else if(op.equals("Backspace"))
           {
               if(k >= 1) k --;
           }
           else
           {
               char t = op.toCharArray()[0];
               if(state)
               {
                   ans[++ k] = (char)(t - ('a' - 'A'));
               }
               else ans[++ k] = t;
           }
       }
       for(int i = 1;i <= k;i ++)
       {
           if(ans[i] == '#') System.out.print(" ");
           else System.out.print(ans[i]);
       }
    }
}

7、删除字符

算法分析

记录所有字母在某些位置出现过用链表记录,比如a字符在2,3,5位置出现过,则用链表存储2,3,5,从az枚举每个链表,标记需要删除的字符,最后枚举所有的元素,若该元素没有删除过则输出

时间复杂度O(n + k)

Java 代码

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    static int N = 100010;
    static char[] g;
    static ArrayList[] list = new ArrayList[26];
    static boolean[] bool = new boolean[N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int k = scan.nextInt();
        g = scan.next().toCharArray();
        for(int i = 0;i < 26;i ++) list[i] = new ArrayList<Integer>();
        for(int i = 0;i < n;i ++)
        {
            int idx = g[i] - 'a';
            list[idx].add(i);
        }
        
        for(int i = 0;i < 26;i ++)
        {
            for(Object item : list[i])
            {
                int x = (int) item;
                bool[x] = true;
                k --;
                if(k == 0) break;
            }
            if(k == 0) break;
        }
        String ans = "";
        for(int i = 0;i < n;i ++)
        {
            if(!bool[i]) ans += g[i];
        }
        System.out.println(ans);
    }
}

8、两个数组

算法分析

a[]数组中,将x转化为x + y,和x - y,能否把a[]全部元素变成一致,

  • 1、先求出一步的最少距离是多少,即求出b[]数组所有元素的最大公约数c
  • 2、判断a[]数组任意的两个元素能否通过走最少距离的走在一起,即判断任意的a[i],和a[j]的距离t = a[i] - a[j],能否全能整除c,若能返回Yes,否则返回false

时间复杂度O(n)

Java 代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
    static int N = 100010;
    static int n, m;
    static int[] a = new int[N];
    static int[] b = new int[N];

    static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        while (T-- > 0) {
            String[] s1 = br.readLine().split(" ");
            n = Integer.parseInt(s1[0]);
            m = Integer.parseInt(s1[1]);
            String[] s2 = br.readLine().split(" ");
            for (int i = 0; i < n; i++)
                a[i] = Integer.parseInt(s2[i]);
            Arrays.sort(a, 0, n);
            String[] s3 = br.readLine().split(" ");
            for (int i = 0; i < m; i++)
                b[i] = Integer.parseInt(s3[i]);
            // 求b数组的最大公约数
            int c = b[0];
            for (int i = 1; i < m; i++) {
                c = gcd(c, b[i]);
            }
            if (c == 1)
                System.out.println("Yes");
            else {
                boolean flag = true;
                // 求a数组的每两个数的间隔是否都是b数组最大公约数的倍数
                for (int i = 1; i < n; i++) {
                    int t = a[i] - a[i - 1];
                    if (t % c != 0) {
                        flag = false;
                        break;
                    }
                }
                if (flag)
                    System.out.println("Yes");
                else
                    System.out.println("No");
            }
        }
    }

}

9、数组求和

算法分析

假设当前a[]数组已固定,b[]数组已经进行了重排列,即f[i,i] = a[i] * b[i]已固定,求图中所有区间的总和

image.png


f[1,1] = a[1] * b[1] * n * 1 = a[1] * n * 1 * b[1]
f[2,2] = a[2] * b[2] * (n - 1) * 2 = a[2] * (n - 1) * 2 * b[2]
...
f[k,k] = a[k] * b[k] * (n - k + 1) * k = a[k] * (n - k + 1) * k * b[k]
...
f[n,n] = a[k] * b[k] * 1 * n = a[k] * 1 * n * b[k]

又由于a[i]是固定的,因此a[i]需要和 (n - i + 1) * i进行连体搭配,即一定是固定的,相当于转换成给定数组A[],重排列B[],求所有A[i] + B[i]总和的最小值,让A[]的第一大与B[]最小搭配,让A[]的第二大合B[]第二小搭配...,即对A[]B[]进行排序,然后进行搭配

时间复杂度 O(nlogn)

Java 代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
    static int N = 100010;
    static int mod = 998244353;
    static int n,m;
    static Long[] a = new Long[N];
    static Long[] b = new Long[N];
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] s1 = br.readLine().split(" ");
        for(int i = 1;i <= n;i ++) a[i] = Long.parseLong(s1[i - 1]);
        String[] s2 = br.readLine().split(" ");
        for(int i = 1;i <= n;i ++) b[i] = Long.parseLong(s2[i - 1]);
        for(int i = 1;i <= n;i ++)
        {
            a[i] = a[i] * (n - i + 1) * i;
        }
        Arrays.sort(a,1,n + 1);
        Arrays.sort(b,1,n + 1);
        long S = 0;
        for(int i = 1;i <= n;i ++)
        {
            S = (S + (a[i] % mod) * b[n - i + 1]) % mod;
        }
        System.out.println(S);
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容