Educational Codeforces Round 12

Educational Codeforces Round 12

原题地址

#题目分数是否AC
ABuses Between Cities1600
BShopping1400
CSimple Strings1300
DSimple Subset1800
EBeautiful Subarrays2100
FFour Divisors2400





A. Buses Between Cities

题目类型  模拟 枚举
题意

  给出 A 市到 B 市和 B 市到 A 市公交车、出发的频率以及需要的时间。判断当坐从 A 市到 B 市的某一辆车时,在到达 B 市的图中遇到的公交车的数量。

分析

  遇到的公交车共有两种

  1. m m m 时刻从前出发但未到站
  2. m m m 时刻之后出发

枚举所有从 B 市出发的车,然后判断是否可以遇到


时间复杂度

   O ( ( 1440 − 300 ) / b ) O((1440 - 300) / b) O((1440300)/b)


代码
 public static void solve() throws IOException {
        int a = nextInt();
        int ta = nextInt();
        int b = nextInt();
        int tb = nextInt();
        char[] s = next().toCharArray();
 
        int m = ((s[0] - '0') * 10 + (s[1] - '0')) * 60 + (s[3] - '0') * 10 + (s[4] - '0');
 
        int cnt = 0;
        for (int i = 300; i < 1440; i += b) {
            if (i + tb > m && i < m + ta) cnt++;
        }
 
        pw.println(cnt);
    }





B. Shopping

题目类型   模拟 暴力

题意

   k k k 个物品排列一排,然后有 n n n 个顾客每人会购买 m m m 件物品。服务员寻找每个物品的任务量是这个物品所在的索引值(从左往右数第几个)。当一个物品被拿走后,则在最左边新添加一个该物品。现在依次给出每个顾客购买的物品,求最终服务员的任务量是多少。


分析

  因为数据范围很小,所以可以模拟购买物品的过程。维护两个数组,一个存储物品排列的状态,另一个维护每个物品对应的索引值。当购买一个物品后需要将这个物品移除并在最左边添加一个该物品,这个操作结束后需要跟新每个物品对应的索引值。


时间复杂度

   O ( n 2 ∗ m ) O(n^2 * m) O(n2m)


代码
 public static void solve() throws IOException {
        int n = nextInt();
        int m = nextInt();
        int k = nextInt();
 
        int[] q = new int[k];
        int[] pos = new int[k];
 
        for (int i = 0; i < k; i++) {
            q[i] = nextInt() - 1;
            pos[q[i]] = i + 1;
        }
 
        int cost = 0;
        while (n-- > 0) {
            for (int i = 0; i < m; i++) {
                int x = nextInt() - 1;
                cost += pos[x];
                remove(q, pos, x);
            }
        }
        pw.println(cost);
    }
 
    public static void remove(int[] q, int[] pos, int x) {
        for (int i = pos[x] - 1; i > 0; i--) q[i] = q[i - 1];
        q[0] = x;
        for (int i = 0; i < q.length; i++) pos[q[i]] = i + 1;
    }





C. Simple Strings


题目类型   暴力

题意

  如果一个字符串 s s s 中所有相邻字符都是不同的,则称这个字符串是一个“简单字符串”。先在给定一个字符串,求将修改尽可能少的字符使这个字符串变为简单字符串,并输出改变后的字符串(如果有多种解,输出任意一个)。


分析

   遍历字符串,当发现当前位置的字符与它前一个字符或后一个字符相同时则该字符需要改变,具体变为哪一个可以从 26 26 26 个字母中选一个与其前后都不同的字符即可(这个过程不会执行 26 次,最多只会执行 3 次)。


时间复杂度

   O ( 3 ∗ n ) O(3 * n) O(3n)


代码
public static void solve() throws IOException {
        char[] s = next().toCharArray();
 
        for (int i = 1, len = s.length; i < len; i++) {
            if (s[i] == s[i - 1]) {
                for (int c = 'a'; c <= 'z'; c++) {
                    if (s[i - 1] != c
                            && ((i + 1 < len && s[i + 1] != c)
                            || i + 1 == len)) {
                        s[i] = (char) c;
                        break;
                    }
                }
            }
        }
 
        for (char c : s) pw.print(c);
        pw.println();
    }





D. Simple Subset

题目类型   数论

题意

  如果一个集合中任意两个数的和都是素数,则称这个集合是一个“简单子集”。现在给定一个数组 a a a,求 a a a 的最大简单子集(含有元素最多的简单子集)。


分析

   首先考虑两个数和的奇偶情况:

  1. 奇 数 + 奇 数 = 偶 数 奇数 + 奇数 = 偶数 +=
  2. 偶 数 + 偶 数 = 偶 数 偶数 + 偶数 = 偶数 +=
  3. 奇 数 + 偶 数 = 奇 数 奇数 + 偶数 = 奇数 +=

  在质数中,除 2 2 2 以外所有的质数都是奇数,所以一个子集中最多包含两个数,因为不论再向集合中添加一个奇数或偶数都会使其和出现非质数。但是对于 1 1 1 要特殊考虑,因为 1 + 1 = 2 1 + 1 = 2 1+1=2, 而 2 2 2 是一个素数。所以当数组中含有 1 1 1 时就会出现两种情况:

  1. 数组中存在一个数 x x x, 且 x + 1 x + 1 x+1 是一个质数,此时最大简单子集就是 { 1 , 1 , … … , 1 , x } \lbrace 1, 1, ……,1, x \rbrace {1,1,1,x}
  2. 数组中不存在一个数 x x x, 且 x + 1 x + 1 x+1 是一个质数,此时最大简单子集就是 { 1 , 1 , … … , 1 } \lbrace 1, 1, ……,1 \rbrace {1,1,1}

  可以通过埃氏筛预处理出所有的素数从而加速判断两个数的和是否是质数。


时间复杂度

   O ( n + n log ⁡ log ⁡ n ) O(n + n\log ^{\log n}) O(n+nloglogn)


代码
    static boolean[] prime = new boolean[2000010];
 
    public static void solve() throws IOException {
        SOE();
 
        int k = nextInt();
 
        int[] a = new int[k];
 
        int cnt = 0;
        for (int i = 0; i < k; i++) {
            a[i] = nextInt();
            if (a[i] == 1) cnt++;
        }
 
        if (cnt >= 2) {
            for (int i = 0; i < k; i++) {
                if (!prime[a[i] + 1] && a[i] != 1) {
                    pw.println(cnt + 1);
                    pw.print(a[i] + " ");
                    while (cnt-- > 0) pw.print(1 + " ");
                    pw.println();
                    return;
                }
            }
 
            pw.println(cnt);
            while (cnt-- > 0) pw.print(1 + " ");
            pw.println();
            return;
        }
 
 
        for (int i = 0; i < k; i++) {
            for (int j = i + 1; j < k; j++) {
                if (!prime[a[i] + a[j]]) {
                    pw.println(2);
                    pw.println(a[i] + " " + a[j]);
                    return;
                }
            }
        }
 
 
        pw.println(1);
        pw.println(a[0]);
    }
 
    public static void SOE() {
        int m = (int) (Math.sqrt(2000010) + 0.5);
        for (int i = 2; i <= m; i++)
            if (!prime[i])
                for (int j = i * i; j < 2000010; j += i) prime[j] = true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值