Codeforces Round 941 (Div. 2) ------ A ---- F (题解)

前情提要:这场全是思维题,一点算法没有,所以脑子好就能上分。但是个人认为这种场没有啥意义,所以t宝不会出题,下次别出了。(狗头保命)

目录

A. Card Exchange:

题目大意:

思路解析:

代码实现:

B. Rectangle Filling:

题目大意:

思路解析:

代码实现:

 C. Everything Nim:

题目大意:

思路解析:

代码实现:

D. Missing Subarray Sum:

题目大意:

思路解析:

代码实现:

E. Folding Strip:

题目大意:

思路解析:

代码实现:

F. Missing Subarray Sum:

题目实现:

思路解析:

代码实现:


A. Card Exchange:

题目大意:

思路解析:

这个题说的就是你有n张牌,每个牌有个数字,你可以选择数字相同的k张牌,然后将其改变为k-1张牌,并且改变后的牌上的数字是任意的。那么可以发现只要我有个数字的牌超过k张,那么我可以一直让k-1这个牌的颜色不变,直到这个数字的牌只有k张,然后我可以将这个k张牌改变为其他颜色的牌,(然后将这个颜色变为k张)那么可以发现最后一定会剩k-1张,如果没有一张颜色的牌的数量超过k张,那么一定会剩n张。

代码实现:

 
import java.util.*;


import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException {

        int t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }
        w.flush();
        w.close();
    }

    static int mod = 998244353;
    static int inf = (int) 1e9;

    public static void solve() throws IOException {
        int n = f.nextInt(); int k = f.nextInt();
        int[] cnt = new int[10000];
        boolean st = false;
        for (int i = 0; i < n; i++) {
            int num = f.nextInt();
            cnt[num]++;
            if (cnt[num] >= k) st = true;
        }
        if (st) w.println(k - 1);
        else w.println(n);

    }

    public static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }


    public static long qkm(long a, long b, long mod) {
        long res = 1;
        while (b > 0) {
            if ((b & 1) == 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }

    public static class Pair {
        int x, y, val;

        public Pair(int ne, int val, int x) {
            this.x = ne;
            this.y = val;
            this.val = x;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return x == pair.x && y == pair.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

    public static class Node {
        int x, y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

    }


    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() throws IOException {

            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public String nextLine() throws IOException {
            String str = null;
            str = reader.readLine();
            return str;
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

B. Rectangle Filling:

题目大意:

思路解析:

可以发现只要四个边都有某个颜色,那么就可以满足题目要求。

代码实现:

 
import java.util.*;


import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException {

        int t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }
        w.flush();
        w.close();
    }

    static int mod = 998244353;
    static int inf = (int) 1e9;

    public static void solve() throws IOException {
        int n = f.nextInt(); int m = f.nextInt();
        char[][] map = new char[n][m];
        for (int i = 0; i < n; i++) {
            map[i] = f.next().toCharArray();
        }
        boolean a1 = false; boolean a2 = false;
        boolean b1 = false; boolean b2 = false;
        boolean c1 = false; boolean c2 = false;
        boolean d1 = false; boolean d2 = false;
        for (int i = 0; i < m; i++) {
            if (map[0][i] == 'W') a1 = true;
            if (map[0][i] == 'B') a2 = true;
        }
        for (int i = 0; i < m; i++) {
            if (map[n-1][i] == 'W') b1 = true;
            if (map[n-1][i] == 'B') b2 = true;
        }
        for (int i = 0; i < n; i++) {
            if (map[i][0] == 'W') c1 = true;
            if (map[i][0] == 'B') c2 = true;
        }
        for (int i = 0; i < n; i++) {
            if (map[i][m-1] == 'W') d1 = true;
            if (map[i][m-1] == 'B') d2 = true;
        }
        if ((a1 && c1 && b1 && d1) || (a2 && b2 && c2 && d2)) w.println("YES");
        else w.println("NO");

    }

    public static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }


    public static long qkm(long a, long b, long mod) {
        long res = 1;
        while (b > 0) {
            if ((b & 1) == 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }

    public static class Pair {
        int x, y, val;

        public Pair(int ne, int val, int x) {
            this.x = ne;
            this.y = val;
            this.val = x;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return x == pair.x && y == pair.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

    public static class Node {
        int x, y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

    }


    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() throws IOException {

            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public String nextLine() throws IOException {
            String str = null;
            str = reader.readLine();
            return str;
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

 C. Everything Nim:

题目大意:

思路解析:

这道题最关键的点就是千万别都错题,我赛时就读错题了哈哈。

他是对于这剩下的n堆石子,你选择的k应当小于等于最小的堆的大小,然后当前所有堆减小k(这里特别关键,我就是赛时没有看到这个信息)。那么如果只要这个石堆中有1这样的石堆,那么他就只能选择1.

那么只要当前最小的石堆为1,那么可以发现你选择一后,其实是让后者赢,除非当前石堆都为1.

例如 1 3 5 6 -- 》 2 4 5 (a) -->1 3 4(b) -->  2 3(a) --> 1 2(b)--> 1(a) -- > win, 可以发现形如 x y z......x>=2的时候,谁先手谁就赢。 先手 可以选择x-1,那么整体变为 1 y-x+1 z-x+1,那么两次处理之后一定会删除一个数字,当只剩下一个石堆时,alice可以直接处理掉。

但是如果x=1,他此时只能选择1,没法使用策略来让自己获胜。

代码实现:



import java.util.*;


import java.io.*;

public class Main {
    static int t;
    public static void main(String[] args) throws IOException {

        t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }
        w.flush();
        w.close();
    }

    static int mod = 998244353;
    static int inf = (int) 1e9;

    public static void solve() throws IOException {
        int n = f.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = f.nextInt();
        }
        Arrays.sort(a);
        int ned = 1;
        int k = 0;
        int mx = a[n-1];
        for (int i = 0; i < n; i++) {
            if (a[i] < ned) continue;
            if (a[i] == ned) {
                ned = a[i] + 1;
                k ^= 1;
                if (a[i] == mx) k ^= 1;
            }
        }
        if (k == 0) w.println("Alice");
        else w.println("Bob");
    }

    public static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }


    public static long qkm(long a, long b, long mod) {
        long res = 1;
        while (b > 0) {
            if ((b & 1) == 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }

    public static class Pair {
        int x, y, val;

        public Pair(int ne, int val, int x) {
            this.x = ne;
            this.y = val;
            this.val = x;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return x == pair.x && y == pair.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

    public static class Node {
        int x, y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

    }


    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() throws IOException {

            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public String nextLine() throws IOException {
            String str = null;
            str = reader.readLine();
            return str;
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

D. Missing Subarray Sum:

题目大意:

思路解析:

给你一个n和k然后利用最多25个数字组成一个序列,保证这个序列的所有子序列和包含(1-n除了k),看到只能使用25个值,很容易想到二进制,那么我们先利用二进制解决(1 - k-1)

那么我们再加入k+1,就可以解决 (1-2k) 再加入 2k 就可以解决 (1-4k) 但其实 (1-2k)中缺少了k,我们并不能解决3*k,所以我们再加入k+1,那么我们真正实现了(1-4k)再加入4k,可以发现此时也真正实现了(1-8k),那么一直往后递归就实现了。 // (注意k==1时应当加入 3)

代码实现:



import java.util.*;


import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException {

        int t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }
        w.flush();
        w.close();
    }

    static int mod = 998244353;
    static int inf = (int) 1e9;

    public static void solve() throws IOException {
        int n = f.nextInt(); int m = f.nextInt();
        int[] a = new int[26];
        int cnt = 0;


        int res = 0;
        for (int i = 0; i <= 20; i++) {
            if (res + (1 << i) <= m - 1){
                a[++cnt] = (1 << i);
                res += (1 << i);
            }else {
                if ((m - 1) - res > 0){
                    a[++cnt] = (m - 1) - res;
                    res += (m - 1) - res - 1;
                }
                break;
            }
        }
        res = m * 2;
        a[++cnt] = m + 1;
        a[++cnt] = m + 1;
        a[++cnt] = m * 2+ 1;
        while (res < n){
            a[++cnt] = res;
            res *= 2;
        }
        w.println(cnt);
        for (int i = 1; i <= cnt; i++) {
            w.print(a[i] + " ");
        }
        w.println();
    }

    public static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }


    public static long qkm(long a, long b, long mod) {
        long res = 1;
        while (b > 0) {
            if ((b & 1) == 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }

    public static class Pair {
        int x, y, val;

        public Pair(int ne, int val, int x) {
            this.x = ne;
            this.y = val;
            this.val = x;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return x == pair.x && y == pair.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

    public static class Node {
        int x, y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

    }


    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() throws IOException {

            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public String nextLine() throws IOException {
            String str = null;
            str = reader.readLine();
            return str;
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

E. Folding Strip:

题目大意:

思路解析:

 通过折叠 一定会将 11111111 (x个1) 折叠为 1, 同理0也是这样的 

那么我们再观察 折叠的 一般形式   x个1 + y个0 + c个1 + c个1 + y个0 + x个1 一定会通过折叠变为 x个1 + y个0 + c个1又可以根据第一个的发现,那么折叠一定会变为 101 同时这样变为了最短形式 (那么可以发现任意一个折叠块都应当可以看作一个1和0交替出现的串)

那么就可以通过模仿这样的折叠来得到最小串长度,即寻找最短的01交替串

并且还可以发现折叠并不会影响其他位置的折叠

代码实现:



import java.util.*;


import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException {

        int t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }
        w.flush();
        w.close();
    }

    static int mod = 998244353;
    static int inf = (int) 1e9;

    public static void solve() throws IOException {
        // 通过折叠 一定会将 11111111 (x个1) 折叠为 1, 同理y也是这样的
        // 那么我们再观察 折叠的 一般形式   x个1 + y个0 + c个1 + c个1 + y个0 + x个1 一定会通过折叠变为 x个1 + y个0 + c个1
        // 又可以根据第一个的发现,那么折叠一定会变为 101 同时这样变为了最短形式 (那么可以发现任意一个折叠块都应当可以看作一个1和0交替出现的串)
        // 那么就可以通过模仿这样的折叠来得到最小串长度
        // 并且还可以发现折叠并不会影响其他位置的折叠
        int n = f.nextInt();
        char[] s = f.next().toCharArray();
        int mx = 0; int mn = 0; int cur = 0;
        for (int i = 0; i < n; i++) {
            if ((cur % 2 == 0) == (s[i] == '1'))
                cur++;
            else cur--;
            mx = Math.max(cur, mx);
            mn = Math.min(cur, mn);
        }
        //w.println(cur);
        w.println(mx - mn);
    }

    public static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }


    public static long qkm(long a, long b, long mod) {
        long res = 1;
        while (b > 0) {
            if ((b & 1) == 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }

    public static class Pair {
        int x, y, val;

        public Pair(int ne, int val, int x) {
            this.x = ne;
            this.y = val;
            this.val = x;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return x == pair.x && y == pair.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

    public static class Node {
        int x, y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

    }


    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() throws IOException {

            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public String nextLine() throws IOException {
            String str = null;
            str = reader.readLine();
            return str;
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

F. Missing Subarray Sum:

题目实现:

思路解析:

经过分析发现,居中的子数组一定是一个,其他的数组是两个,那么应当有 (n+1)/2个居中数组,并且利用居中数组可以很方便的还原原数组。

那么假设我们丢失了一个居中的数组:我们只能用剩下的居中数组构造一个类似原数组的数组。

假设原数组为 1 2 3 2 1, 居中数组为 3 7 9,现在丢失7,那么我们可以利用剩下的居中数组,构造一个类似还原的数组为 3 3 3,我们可以发现只要丢失一个居中数组,那么我们在还原时,将某两个相邻数字合并 (丢失最大的时会把最后一个舍去 即 2 3 2)

那么假设现在数组为  a b c d c b a,   假设我们丢失最大的居中数组 我们可以利用 b c d c b,这个数组找到最大的子数组和为 (a+b+c+d+c+b) 利用这个和 (b+c+d+c+b)就可以得到想要的答案了,

假设我们丢失某个居中数组,得到还原数组 为 a (b+c) d (c+b) a, 除去在以得到的子数组和中除去还原的数组的子数组和的最大值 (a+c+d+c+b) * 2- (a+b+c+d+c+b+a) 来得到缺失的居中子数组和

假设我们缺失的为非居中子数组,那么我们就会让某个偶数的子数组和,变为奇数,此时就会让居中子数组变多, 策略就变为找到 这个还原数组的子数组和减去已有的子数组和 中最大的那个设为x,答案就是 x*2 - y,y是数组的整体和。

代码实现:

#include <bits/stdc++.h>
#include <unistd.h>

using namespace std;
using i64 = long long;
#define all(a) begin(a),end(a)
vector<i64> getArr(vector<i64> d, bool st){
    deque<i64> q = {d[0]};
    if (not st) q = {d[0] / 2, d[0]/2};
    for(int i = 1; i < d.size(); i++){
        q.push_front((d[i] - d[i-1])/2);
        q.push_back((d[i]-d[i-1])/2);
    }
    return vector(all(q));

}
void solve(){
    int n;
    cin >> n;
    vector<i64> a(n*(n+1)/2-1);
    for(int i = 0; i < n*(n+1)/2-1; ++i){
        cin >> a[i];
        a[i] *= 2;
    }
    sort(all(a));
    vector<i64> e;
    for (auto x : a){
        if (e.size() && e.back() == x) e.pop_back();
        else e.push_back(x);
    }
    vector<i64> b = getArr(e, n & 1);
    vector<i64> B {0};
    vector<i64> a2;
    i64 s = 0;
    for(auto x : b) B.push_back(s+=x);

    for(int i = 0; i < B.size(); ++i){
        for(int j = i+1; j < B.size(); ++j){
            a2.push_back(B[j] - B[i]);
        }
    }

    sort(all(a2));
    if(a2.size() > a.size()) swap(a,a2);
    int i = 0;
    for(; a.rbegin()[i] == a2.rbegin()[i] ; ++i);
    i64 x = 2 * a.rbegin()[i] - s;
    if(e.size() > (n+1) / 2) e.erase(find(all(e),x));
    else e.insert(lower_bound(all(e),x),x);
    vector<i64> ans = getArr(e, n&1);
    for(auto x : ans){
        cout << x/2 << " ";
    }
    cout << "\n";



}


int main()
{
    cin.tie(0) -> sync_with_stdio(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t){
        solve();
        t--;
    }


    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Studying~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值