zoukankan      html  css  js  c++  java
  • [Atcoder]AIsing Programming Contest 2020 Solutions(A-E)

    Before the Beginning

    转载请将本段放在文章开头显眼处,如有二次创作请标明。

    原文链接:https://www.codein.icu/atcoderals/

    前言

    Atcoder的一场比赛,较有乐趣((

    场上做出ABCD,赛后补E,F题还不会。

    A、B:签到题 Easy Problems.

    C:暴力枚举 Bruteforce

    D:思维题 Interesting

    E:贪心题 Greedy

    F:大概可能是组合题?Unknown...

    A

    Statement

    How many multiples of (d) are there among the integers between (L) and (R) (inclusive)?

    Solution

    The range is so small that we can easily brute force.

    #include <cstdio>
    #include <ctype.h>
    const int bufSize = 1e6;
    inline char nc()
    {
        #ifdef DEBUG
        return getchar();
        #endif
        static char buf[bufSize],*p1 = buf,*p2 = buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,bufSize,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>
    inline T read(T &r)
    {
        static char c;
        r=0;
        for(c = nc();!isdigit(c);) c = nc();
        for(;isdigit(c);c=nc()) r = r * 10 + c - 48;
        return r;
    }
    int L,R,d;
    int main()
    {
        read(L),read(R),read(d);
        int ans = 0;
        for(int i = L;i<=R;++i) ans += !(i%d);
        printf("%d
    ",ans);
        return 0;
    }
    

    B

    Statement

    We have (N) squares assigned the numbers (1,2,3,ldots,N). Each square has an integer written on it, and the integer written on Square (i) is (a_i).

    How many squares (i) satisfy both of the following conditions?

    • The assigned number, (i), is odd.
    • The written integer is odd.

    Solution

    just easily brute force.

    #include <cstdio>
    #include <ctype.h>
    const int bufSize = 1e6;
    inline char nc()
    {
        #ifdef DEBUG
        return getchar();
        #endif
        static char buf[bufSize],*p1 = buf,*p2 = buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,bufSize,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>
    inline T read(T &r)
    {
        static char c;
        r=0;
        for(c = nc();!isdigit(c);) c = nc();
        for(;isdigit(c);c=nc()) r = r * 10 + c - 48;
        return r;
    }
    const int maxn = 110;
    int n;
    int a[maxn];
    int main()
    {
        read(n);
        for(int i = 1;i<=n;++i) read(a[i]);
        int ans = 0;
        for(int i = 1;i<=n;i += 2)  ans += a[i] % 2;
        printf("%d
    ",ans);
        return 0;
    }
    

    C

    Statement

    Let (f(n)) be the number of triples of integers ((x,y,z)) that satisfy both of the following conditions:

    • (1 leq x,y,z)
    • (x^2 + y^2 +z^2 + xy + yz + zx = n)

    Given an integer (N),find each of (f(1),f(2),ldots,f(N)).

    (1 leq N leq 10^4)

    Solution

    We can enumerate every possible triple to add the ans to (f(result)).

    It's easy to see that (x,y,z leq sqrt{n}), so we can stop the loop when the future result will always be larger than (n).

    #include <cstdio>
    #include <ctype.h>
    const int bufSize = 1e6;
    inline char nc()
    {
        #ifdef DEBUG
        return getchar();
        #endif
        static char buf[bufSize],*p1 = buf,*p2 = buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,bufSize,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>
    inline T read(T &r)
    {
        static char c;
        r=0;
        for(c = nc();!isdigit(c);) c = nc();
        for(;isdigit(c);c=nc()) r = r * 10 + c - 48;
        return r;
    }
    const int maxn = 1e4 + 100;
    int x,y,z,n;
    int f[maxn];
    inline int calc()
    {
        return x * x + y * y + z * z + x * y + x * z + y * z;
    }
    int main()
    {
        read(n);
        for(x = 1;x<=1000;++x)
        {
            for(y = 1;y<=1000;++y)
            {
                if(x * x + y * y + x * y > n) break;
                for(z = 1;z<=1000;++z)
                {
                    int t = calc();
                    if(t > n) break;
                    f[t]++;
                }
            }
        }
        for(int i = 1;i<=n;++i) printf("%d
    ",f[i]);
        return 0;
    }
    

    D

    Statement

    Let (operatorname{popcount}(n)) be the number of 1s in the binary representation of (n). For example, (operatorname{popcount}(3)=2), (operatorname{popcount}(7)=3), and (operatorname{popcount}(0)=0).

    Let (f(n)) be the number of times the following operation will be done when we repeat it until (n) becomes (0): "replace (n) with the remainder when (n) is divided by (operatorname{popcount}(n))." (It can be proved that, under the constraints of this problem, (n) always becomes (0) after a finite number of operations.)

    For example, when (n=7), it becomes (0) after two operations, as follows:

    • (operatorname{popcount}(7)=3), so we divide (7) by (3) and replace it with the remainder, (1).
    • (operatorname{popcount}(1)=1), so we divide (1) by (1) and replace it with the remainder, (0).

    You are given an integer (X) with (N) digits in binary. For each integer (i) such that (1 leq i leq N), let (X_i) be what (X) becomes when the (i)-th bit from the top is inverted. Find (f(X_1),f(X_2),ldots,f(X_N)).

    (1 leq N leq 2 imes 10^5)

    Solution

    The given "integer" (X) is so big that we have to transform it into an acceptable range.

    It can be proved that after an operation, (n) would be smaller than (operatorname{popcount}(n)), and we can see that (operatorname{popcount}(X) leq N), so maybe we can use an operation to make (X) smaller.

    Considering that for (X_i), we invert the (i)-th bit, which means (popcount(X_i) = popcount(X) + 1) when the (i)-th bit is originally (0) and the vice versa.

    So we can do the first operation while (mod operatorname{popcount}(X) + 1) or (mod operatorname{popcount}(X) - 1).

    Assume that (t_1 = operatorname{popcount}(X) + 1),(t_2 = operatorname{popcount}(X) - 1).

    Then for (X_i):

    1. The (i)-th bit is originally (0),(X_i = X + 2^i,operatorname{popcount}(X_i) = t_1), after the one origin operator we can get that (val = X + 2^i pmod {t_1}).
    2. The (i)-th bit is originally (1),(X_i = X - 2^i,operatorname{popcount}(X_i) = t_2), after the one origin operator we can get that (val = X - 2^i pmod {t_2}).

    The (val) is the result after first operation. It's easy to see that (val leq t_1), which means we can brute force to do the remaining operation to get the answer, and the time complexity is (O(log val)).

    After all, for every (X_i) we calculate the (val) and do the brute force, then we can solve the problem in (O(n log n)).

    Note that (t_2) may equal to zero.

    Code

    We first calculate (X,2^i pmod {t_1}),(X,2^i pmod {t_2}).

    And in one single calculation we can get (val) for (X_i).

    #include <cstdio>
    #include <ctype.h>
    #define DEBUG
    const int bufSize = 1e6;
    inline char nc()
    {
        #ifdef DEBUG
        return getchar();
        #endif
        static char buf[bufSize],*p1 = buf,*p2 = buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,bufSize,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>
    inline T read(T &r)
    {
        static char c;
        r=0;
        for(c = nc();!isdigit(c);) c = nc();
        for(;isdigit(c);c=nc()) r = r * 10 + c - 48;
        return r;
    }
    const int maxn = 2e7 + 100;
    char s[maxn];
    int n;
    int f1[maxn],f2[maxn];
    inline int popcount(int x)
    {
        int ans = 0;
        while(x) ans += x & 1,x>>=1;
        return ans;
    }
    inline int opt(int x)
    {
        int ans = 0;
        while(x) x %= popcount(x),++ans;
        return ans;
    }
    int main()
    {
        read(n);
        scanf("%s",s + 1);
        int t = 0,t1 = 0,t2 = 0;
        for(int i = 1;i<=n;++i) t += (s[i] == '1');
        t1 = t + 1,t2 = t - 1;
        f1[n] = f2[n] = 1;
        for (int i = n - 1; i; --i) 
        {
            f1[i] = (f1[i + 1] * 2) % t1;
            if(t2 != 0) f2[i] = (f2[i + 1] * 2) % t2;
        }
        int temp1 = 0,temp2 = 0;
        for(int i = 1;i<=n;++i)
        {
            temp1 <<= 1,temp2 <<= 1;
            temp1 += s[i] - 48,temp1 %= t1;
            if(t2 != 0) temp2 += s[i] - 48,temp2 %= t2;
        }
        for (int i = 1; i <= n; ++i)
        {
            if(s[i] == '1')
            {
                if(t2 == 0)
                {
                    printf("0
    ");
                    continue;
                }
                int val = ((temp2 - f2[i]) % t2 + t2) % t2;
                printf("%d
    ",opt(val) + 1);
            }
            else 
            {
                int val = (temp1 + f1[i] + t1) % t1;
                printf("%d
    ",opt(val) + 1);
            }
        }
        return 0;
    }
    

    E

    Statement

    We have (N) camels numbered (1,2,ldots,N).

    Snuke has decided to make them line up in a row.

    The happiness of Camel (i) will be (L_i) if it is among the (K_i) frontmost camels, and (R_i) otherwise.

    Snuke wants to maximize the total happiness of the camels. Find the maximum possible total happiness of the camel.

    Solve this problem for each of the (T) test cases given.

    (1 leq T leq 10^5)

    (1 leq N leq 2 imes 10^{5})

    (1 leq K_i leq N)

    (1 leq L_i, R_i leq 10^9)

    The sum of values of (N) in each input file is at most (2 imes 10^5).

    Solution

    We can divide the camels into two sets:

    • A: L > R,which means it's better to be the left one.
    • B: R > L,which means it's better to be the right one.

    In each set we sort the camels by (K), and enumerate (i) to decide whether the camel should be in the right position.

    We can use a priority_queue to store the chosen camels, and see if the camel now is better than the worst camel we've chosen. If yes, we can give up the chosen camel and choose the camel now to get better result.

    For example, assume that we are modifying the set A, the (size) refers to how many camels have been chosen:

    1. (size < K_i), we can simply choose the camel.
    2. (size = K_i), we can compare the camel now with the worst camel chosen and see if we can replace it. If so, we pop the old worst camel and push the better camel now into the chosen set.

    Code

    Note that we sort the camels in set A by (K), and sort the camels in set B by (n - k).

    And we have to be aware of the situation that (K_i = 0), which may lead to Runtime Error as we try to pop while no element is in.

    We first assume that we can only get (sum operatorname{min}(L,R)) and then calculate how many more we can gain by managing the camels.

    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <ctype.h>
    #define DEBUG
    const int bufSize = 1e6;
    using namespace std;
    inline char nc()
    {
    #ifdef DEBUG
        return getchar();
    #endif
        static char buf[bufSize], *p1 = buf, *p2 = buf;
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufSize, stdin), p1 == p2) ? EOF : *p1++;
    }
    template <typename T>
    inline T read(T &r)
    {
        static char c;
        r = 0;
        for (c = nc(); !isdigit(c);) c = nc();
        for (; isdigit(c); c = nc()) r = r * 10 + c - 48;
        return r;
    }
    const int maxn = 2e5 + 100;
    int T, n, anum, bnum;
    struct node
    {
        int L, R, K;
        bool operator<(const node &b) {return K < b.K;}
    } A[maxn], B[maxn];
    priority_queue<int, vector<int>, greater<int> > q1, q2;
    int main()
    {
        read(T);
        while (T--)
        {
            anum = bnum = 0;
            long long ans = 0;
            read(n);
            for (int i = 1; i <= n; ++i)
            {
                int k, l, r;
                read(k), read(l), read(r);
                if (l > r) A[++anum].L = l, A[anum].R = r, A[anum].K = k;
                else B[++bnum].L = l, B[bnum].R = r, B[bnum].K = n - k;
                ans += std::min(l, r);
            }
            sort(A + 1, A + 1 + anum), sort(B + 1, B + 1 + bnum);
            for (int i = 1; i <= anum; ++i)
            {
                if (A[i].K == 0) continue;
                if (q1.size() < A[i].K) q1.push(A[i].L - A[i].R);
                else if (q1.size() == A[i].K && q1.top() < A[i].L - A[i].R) q1.pop(), q1.push(A[i].L - A[i].R);
            }
            for (int i = 1; i <= bnum; ++i)
            {
                if (B[i].K == 0) continue;
                if (q2.size() < B[i].K) q2.push(B[i].R - B[i].L);
                else if (q2.size() == B[i].K && q2.top() < B[i].R - B[i].L) q2.pop(), q2.push(B[i].R - B[i].L);
            }
            while (!q1.empty()) ans += q1.top(), q1.pop();
            while (!q2.empty()) ans += q2.top(), q2.pop();
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    OutOfMemoryError异常穷举
    Java的锁优化
    Java的线程安全
    Java的线程模型
    算法笔记_014:合并排序(Java)
    算法笔记_013:汉诺塔问题(Java递归法和非递归法)
    算法笔记_012:埃拉托色尼筛选法(Java)
    算法笔记_011:希尔排序
    算法笔记_010:插入排序(Java)
    算法笔记_009:字符串匹配(Java)
  • 原文地址:https://www.cnblogs.com/Clouder-Blog/p/atcoderals.html
Copyright © 2011-2022 走看看