[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\n",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\n",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\n",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 \times 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\n");
                continue;
            }
            int val = ((temp2 - f2[i]) % t2 + t2) % t2;
            printf("%d\n",opt(val) + 1);
        }
        else 
        {
            int val = (temp1 + f1[i] + t1) % t1;
            printf("%d\n",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 \times 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 \times 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\n", ans);
    }
    return 0;
}
posted @ 2020-07-12 12:25  *Clouder  阅读(266)  评论(0编辑  收藏  举报