SDNU_2020Shenyang_Qualification problem solution

Posted by jhuaraya on Fri, 18 Feb 2022 07:42:23 +0100

C Gym - 102822D

analysis:
The answer is monotonous and can be divided into two points. Then the focus is on the writing of the judgment function. Let's assume that the answer is X. because this question needs to reduce the bomb by - 1 before it explodes, it's very awkward. Let's first consider the case that the bomb explodes when it reaches 0. If the bomb explodes when it reaches 0, then we find that each bomb less than x needs a chance round of plus 1 operation, That is, (x-ar[i]), find the sum of this number, and finally judge the size relationship with X.
Tips for not knowing whether to use:
1. If the boundary is awkward and you don't understand it during the competition, write a correct judgment function, and then output the numbers mid-5~mid+5. Try next to each other. Anyway, the answer is near mid.
2. If the upper bound of the dichotomy of this question is different, it will be different???, In the future, if the two points are wa, we can consider changing the upper bound and sending it again.

AC Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int t, n;
ll ar[100005];
ll sum;
ll l ,r, mid;

bool judge(ll x)
{
    sum = 0;
    x--;//Because the calculation is x-ar[i], that is, the number of rounds required to be reduced to 0, and the title requirement is to be reduced to - 1, so here -- (gray is often difficult to understand)
    for(int i = 1; i <= n; ++i)
    {
        if(ar[i] < x) sum += (x - ar[i]);
    }
    if(sum <= x) return true;
    else return false;
}

int main()
{
    scanf("%d", &t);
    for(int p = 1; p <= t; ++p)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) scanf("%lld", &ar[i]);
        l = 1; r = 1e14;
        while(l <= r)
        {
            mid = (l + r) / 2;
            if(judge(mid)) l = mid + 1;
            else r = mid - 1;
        }
        printf("Case #%d: %d\n", p, l - 1);
    }
    return 0;
}

G CodeForces - 1260C

Meaning:
There are infinite walls. Here are three numbers r, B and k. The multiple of r (0, r, 2r,...) is painted red, and the multiple of B (0, b, 2b,...) is painted blue, that is, the multiple of r is also the multiple of B. It is OK to paint red and blue. Remove the wall that is not painted. Finally, look at the relationship between the length of the longest continuous wall of the same color and k. if it is greater than or equal to k, the person will die and output REBEL, otherwise output OBEY (the person should not want to go West)
analysis:
Obviously, take mx = max(r, b), mi = min(r,b), find out the maximum number of multiples of mi in the interval between kmx and (k + 1) mx, and then judge the relationship with k. to make the multiples of mi as many as possible, let the multiples of the first mi be as high as possible in the interval. Assuming that it is at t of the interval, then the equation k1*mx + t = k2 * mi is satisfied.
As exgcd knows, the equation ax + by = c has a solution if and only if c can be divided by gcd (a, b). So t is at least equal to gcd (mx, mi)
AC Code:

#include <bits/stdc++.h>

using namespace std;

int t;
int r, b, k;
int mx, mi;
int x, y;
int sum;

inline int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}

int main()
{
    cin >> t;
    while(t--)
    {
        cin >> r >> b >> k;
        mx = max(r, b);
        mi = min(r, b);
        x = gcd(r, b);
        y = mx - 1;
        sum = (y - x) / mi + 1;
        if(sum < k) printf("OBEY\n");
        else printf("REBEL\n");
    }
    return 0;
}

CodeForces - 264B

Meaning:
Give you a strictly ascending sequence, which requires you to find the longest subsequence. This subsequence needs to meet the GCD > 1 of any two adjacent elements, and output the length of this sequence.
analysis:
dynamic programming
dp[i], representing the longest length of the sequence in which the last element has a factor I
Therefore, we need to preprocess the factor of each element
Then, for each element, after updating the dp values corresponding to all its factors, we need to change the dp values corresponding to all its factors to the largest one, because these sequences end with the same element. for instance.

dp[2] = 3 The corresponding sequence is 9 18 20
dp[4] = 2 The corresponding sequence is 18 20
dp[5] = 1 The corresponding sequence is 20
dp[10] = 1 The corresponding sequence is 20
dp[20] = 1 The corresponding sequence is 20
 When the last element of these sequences is 20, then dp[2,4,5,10,20]The corresponding sequence can be 9, 18 and 20, so it needs to be updated to the maximum value

Finally, it should be noted that there is an example with only one number (it seems that this number is still 1, and there is no statistics dp[1]) in this practice. Let's judge it.
AC Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
    return x * w;
}
int n, x, a, sq, b;
int mx, len;
int ar[100050];
int dp[100050];
vector<int> vt[100050];
int ans;

void dio(int x)
{
    a = ar[x];
    sq = sqrt(a);
    vt[x].push_back(a);
    for(int i = 2; i <= sq; ++i)
    {
        if(a % i == 0)
        {
            vt[x].push_back(i);
            if(i*i != a) vt[x].push_back(a/i);
        }
    }
}

int main()
{
    n = read();
    for(int i = 1; i <= n; ++i)
    {
        ar[i] = read();
        dio(i);
    }
    for(int i = 1; i <= n; ++i)
    {
        mx = 0;
        len = vt[i].size();
        for(int j = 0; j < len; ++j)
        {
            b = vt[i][j];
            ++dp[b];
            mx = max(mx, dp[b]);
        }
        for(int j = 0; j < len; ++j) dp[vt[i][j]] = mx;
    }
    for(int i = 1; i <= ar[n]; ++i) ans = max(ans, dp[i]);
    printf("%d\n", ans);
    return 0;
}

Topics: C++ Dynamic Programming Binary Search ICPC