Codeforces Round 907 (Div. 2) 题解 A-B

目录

  • [A - Sorting with Twos](#A - Sorting with Twos)
  • [B - Deja Vu](#B - Deja Vu)

A - Sorting with Twos

原题链接

题目描述

给你一个长度为 n n n 的数组 a a a,在每次操作中,你可以选择一个非负整数 m m m ( 2 m ≤ n 2^m \leq n 2m≤n),然后让所有的 a i a_i ai ( 1 ≤ i ≤ 2 m 1 \le i \leq 2^m 1≤i≤2m)都减去 1 1 1,问是否可以通过一定次数使得数组 a a a 变成非递减数组。

思路:思维+暴力修改

  • 由于 n n n很小,我们每次从坐标 1 1 1开始,往后暴力修改每一个长度为 2 m 2^m 2m的区间,这样一定可以让前面的更小,如果这样修改都无法满足,那么为No
java 复制代码
public static void solve() throws IOException{
    int n = readInt();
    int[] arr = utils.nextIntArray(n);
    int m = 0;
    boolean f = true;
    int k = 10;
    while (k-- > 0) {
    	// 如果在修改区间时,已经遇到arr[i - 1] > arr[i],那么肯定无法满足题意
    	// 因为该区间已经不可再分,即无法将arr[i - 1]变为更小的值
        for (int i = 1; i <= Math.pow(2, m) && i <= n; i++) {
            if (arr[i - 1] > arr[i]) {
                f = false;
                break;
            }
        }
        if (!f) break;
        // 暴力将前面都修改为最小值
        for (int i = 1; i <= Math.pow(2, m) && i <= n; i++) {
            arr[i] = 0;
        }
        m++;// 增加区间长度
    }
    printWriter.println(f ? "YES" : "NO");
}

B - Deja Vu

原题链接

题目描述

给你一个长度为 n n n 的正整数数组 a a a 和一个长度为 q q q 的正整数数组 x x x,一共有 q q q 次修改,对于每次修改,如果 a j ( 1 ≤ j ≤ n ) a_j(1 \leq j \leq n) aj(1≤j≤n)可以被 2 x i ( 1 ≤ i ≤ q ) 2^{x_i}(1 \leq i \leq q) 2xi(1≤i≤q)整除,那么就把 2 x i − 1 2^{x_i-1} 2xi−1 加到 a j a_j aj 上。求在完成 q q q 次修改后的 a a a 数组。

思路:思维+观察

  • 如果 a j a_j aj 可以被 2 x i 2^{x_i} 2xi整除,那么当 a j a_j aj加上 2 x i − 1 2^{x_{i-1}} 2xi−1后, a j a_j aj之后可以整除的 2 x k 2^{x_k} 2xk 一定小于 2 x i 2^{x_i} 2xi,即 k < i k \lt i k<i,比如 32 32 32 可以整除 2 5 2^5 25 ( i = 5 ) (i = 5) (i=5),那么 32 32 32 加上 2 4 ( i − 1 = 4 ) 2^4(i-1 = 4) 24(i−1=4)后变为 48 48 48 ,而 48 48 48 只能整除 2 p ( p < 5 ) 2^p(p \lt 5) 2p(p<5)。
  • 所以对于每一个 a j a_j aj,当他可以整除 x i x_i xi时,求出 x i x_i xi在 x x x数组中的严格下降子序列即可。但是 x i x_i xi的严格下降子序列我们应该预处理好。
java 复制代码
public static void solve() throws IOException{
    int n = readInt(), q = readInt();
    int[] a = utils.nextIntArray(n);
    int[] x = utils.nextIntArray(q);
    List<Integer>[] lists = new List[40];
    Arrays.setAll(lists, g -> new ArrayList<>());
    for (int i = 1; i <= 30; i++) {
        lists[i].add(40);// xi最大为30,这里我们添加一个更大的值,保证降序
    }
    // 求出 xi的严格下降序列
    for (int i = 1; i <= 30; i++) {
        for (int j = 1; j <= q; j++) {
            if (x[j] < lists[i].get(lists[i].size() - 1)) {//比上一次的小就添加
                lists[i].add(x[j]);
            }
        }
    }
    int[] have= new int[40];// xi是否出现过
    for (int i = 1; i <= q; i++) {
        if (have[x[i]] == 0) {
            have[x[i]] = i;
        }
    }
    for (int i = 1; i <= n; i++) {
    	// 求出 ai的因数可以有多少个 2
        int k = 0, t = a[i];
        while (t % 2 == 0 && t != 0) {
            k++;
            t /= 2;
        }
        // 求出最近的能被 ai整除的 x数组的数 x^k
        while (k >= 1 && have[k] == 0) {
            k--;
        }
        // 根据 x^k的严格下降序列,求出最终的 ai
        List<Integer> ps = lists[k];
        for (Integer p : ps) {
            if (a[i] % Math.pow(2, p) == 0) {
                a[i] += Math.pow(2, (p - 1));
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        printWriter.print(a[i] + " ");
    }
    printWriter.println();
}
相关推荐
白榆maple9 分钟前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少13 分钟前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋1 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
咕咕吖2 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
九圣残炎2 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu2 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
丫头,冲鸭!!!3 小时前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
Re.不晚3 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
为什么这亚子4 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
4 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习