Solution to the problem of Niuke Xiaoyue race 41 (A~F)

Keywords: C++ Algorithm

Today is lzgg a question, a special session for Xiao Hong; The topic is not very difficult, but the website always collapses during the competition, so the experience is not very comfortable;

A. Xiao Hong's sign in question

Title: Portal

Question meaning: a question, a total of b people participated, and the total number of questions passed by all is c. ask how many people have completed all the questions at most;

Solution: simple check-in question, which almost won the first a, QAQ; Directly dividing c by a without calculating the remainder is the answer;

AC Code:

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    int a, b, c;
    cin>>a>>b>>c;
    cout<<c/a<<endl;
    return 0;
}

B. Xiao Hong's ABC

Title: Portal

Question meaning: give you a string s to judge the length of the shortest palindrome string with a length of more than 1 in the substring of this string. If not, output - 1;

Problem solving idea: take a look at the data range. The length of the string does not exceed 100. What else is needed in this data range? Directly enumerate each string with a length greater than 2, see if it is a palindrome string, and then find the minimum length;

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    string s;
    cin>>s;
    int n = s.length();
    int ans = 0x3f3f3f3f;//Maintain the palindrome string length with the minimum substring length
    string c, t;
    for(int i = 0; i<n; i++){
        for(int j = i+1; j<n; j++){
            c = "", t = "";
            for(int k = i; k<=j; k++) c+=s[k], t+=s[j-k+i];
            // for(int k = c.length()-1; k>=0; i--) t+=c[k];
            // cout<<c<<endl;
            // cout<<t<<"***"<<endl;
            if(c == t){//Determine palindrome string
                ans = min(ans, j-i+1);
            }
        }
    }
    if(ans == 0x3f3f3f3f) puts("-1");
    else cout<<ans<<endl;
    return 0;
}

C. Little red's mask

Title: Portal

Topic meaning: in other words, Xiao Hong can eat food weighing k. now there are n foods, and the weight of each food is a[i]. Every time Xiao Hong eats a food weighing x, there will be an additional food weighing 2*x. ask Xiao Hong how many foods she can eat at most;

Solution idea: first of all, we can see that we are greedy to get the minimum every time. If we directly use array storage to get the minimum every time, the time complexity is O(nnk), and it will timeout. Therefore, we can choose to use small root heap to store, so that insertion and deletion are longn; For the small root heap, you can directly use the priority in stl_ Queue, detailed usage, self query;

AC Code:

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;

struct cmp1
{
    bool operator ()(int &a,int &b)
    {
        return a>b;
    }
};
priority_queue <int,vector<int>, cmp1> q;//Small root pile

const int N = 100005;

int main()
{
    int n, k, x;
    scanf("%d%d", &n, &k);
    for(int i = 1; i<=n; i++){
        scanf("%d", &x);
        q.push(x);
    }
    int ans = 0;
    while(k&&!q.empty()){
        int t = q.top();
        q.pop();
        if(t>k) break;
        k-=t;
        ans++;
        if((ll)t*2<=1e9){
            q.push(t*2);
        }
    }
    cout<<ans<<endl;
    return 0;
}

D. Array of little red

Title: Portal

Xiaohong has an array a with a length of n. find two numbers in the array at the same time, and output the number of schemes whose product is greater than k, equal to K and less than k respectively;

Solution: according to the official solution given by lzgg, this problem can be solved by dichotomy and double pointer. I solved it by dichotomy. Of course, dichotomy needs to pay attention to boundary conditions. I suffered two losses here; The premise of bisection is to sort the given array from small to large. After sorting, for each a[i], we need to find the boundary of k/a[i] (we can directly use the bisection function in stl). Here, we should pay attention to the classification and discuss whether we can divide it; The three situations we require:

1. When the product is equal to K: this situation exists only when k can divide a[i] and array a contains k/a[i]. For the quantity of k/a[i], you can save the quantity in map in advance. Note that when a[i] == k/a[i], you need to subtract 1 (because you can't take the number in one position at a time);

2. When the product is greater than K: in this case, if K can divide a[i], find the position (upper_bound())tot of the first number greater than k/a[i], and the following n-tot+1 numbers and other combinations meet this situation. Pay attention to judge whether a[i] is after tot at this time. If so, the number of schemes will be reduced by 1 (because the number at one position cannot be taken at the same time); when k cannot divide a[i], it is similar;

3. When the product is less than k: this case is opposite to the second case, so I won't repeat it;

At this time, the answer obtained by dichotomy will cause the number [x, y] at the same two positions to be taken once and [y, x] to be taken once, which will make the final answer exactly twice the standard answer, and the final answer needs to be divided by 2;

AC Code:

#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;

const int N = 300005;

ll a[N];

map<ll, int> ma;

int main()
{
    int n;ll k;
    scanf("%d%lld", &n, &k);
    for(int i = 1; i<=n; i++) scanf("%lld", &a[i]), ma[a[i]]++;
    sort(a+1, a+n+1);
    ll t;
    ll ans = 0, res = 0, num = 0;
    a[n+1] = 0x3f3f3f3f;
    for(int i = 1; i<=n; i++){
        t = a[i];
        ll p = k/t;
        if(k%t == 0){
            int tot = lower_bound(a+1, a+n+1, p) - a;
            if(p == a[tot]) {
                ans+=ma[p];
                if(p == a[tot]) ans--;
            }
            res+=tot-1; if(t<a[tot]) res--;
            tot = upper_bound(a+1, a+n+1, p)-a;
            num+=n - tot + 1; if(t>=a[tot]) num--;
        }
        else{
            int tot = upper_bound(a+1, a+n+1, p) - a;
            res+=tot-1; if(t<a[tot]) res--;
            num+=n-tot+1; if(t>=a[tot]) num--;
        }
    }
    cout<<num/2ll<<' '<<ans/2ll<<' '<<res/2ll<<endl;
    return 0;
}

E. Xiaohong's rpg game

Title: Portal

Topic meaning: give you a map of nm size. Xiaohong needs to walk from the upper left corner to the lower right corner, and there are '.' the road can be walked directly ',' the fence can't be walked, 'the number of 0 ~ 9', which means that it takes a given amount of blood to walk this point. Xiaohong has h drops of blood. Find out how many squares Xiaohong needs to walk from the upper left corner to the lower right corner (Note: no more than 10 number squares);

Solution: if there is no number grid, then this problem is a classic bfs shortest path problem. However, if there are no more than 10 conditional number grids in the problem, we can enumerate whether each number grid is selected or not. If it is not selected, then this number grid can be regarded as a '*' and cannot be passed. If it is selected, we need to judge Xiaohong's blood Whether the quantity h can support all the digital grids, just do dfs for each state of the enumeration, because the enumeration can be binary pressed with or without 10 grids selected;

Last night, I was blind and didn't see that the number of squares was no more than 10. I had been thinking about dp practice. As a result, I didn't see question F. dp always hurts;

AC Code:

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

const int N = 100;
string s[N];
int v[N][N];
struct lq{
    int x, y, h;
    lq(int x, int y, int h): x(x), y(y), h(h){}
};
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int n, m, h;
vector<lq>a;

int main()
{
    scanf("%d%d%d", &n, &m, &h);
    for(int i = 0; i<n; i++) cin>>s[i];
    for(int i = 0; i<n; i++){
        for(int j = 0; j<m; j++){
            if(s[i][j]>='0'&&s[i][j]<='9'){
                a.push_back(lq(i, j, s[i][j] - '0'));
            }
        }
    }
    int ans = 0x3f3f3f3f;
    for(int i = 0; i<1<<a.size(); i++){
        int sum = 0;
        for(int j = 0; j<a.size(); j++){
            if((1<<j)&i) v[a[j].x][a[j].y] = 1, sum+=a[j].h;
            else v[a[j].x][a[j].y] = 0;
        }
        if(sum>=h) continue;
        queue<pair<int,int> >q;
        q.push({0,0});
        int st[N][N] = {};
        memset(st, -1, sizeof st);
        st[0][0] = 0;
        while(!q.empty()){
            pair<int, int>t = q.front();
            q.pop();
            for(int j = 0; j<4; j++){
                int x = t.first+dx[j], y = t.second+dy[j];
                if(x<0||x>=n||y<0||y>=m||st[x][y]!=-1) continue;
                if(s[x][y] == '.'||(s[x][y]!='*'&&v[x][y])){
                    st[x][y] = st[t.first][t.second]+1;
                    q.push({x, y});
                }
            }
        }
        if(st[n-1][m-1]!=-1) ans = min(ans, st[n-1][m-1]);
    }
    if(ans == 0x3f3f3f3f) puts("-1");
    else cout<<ans<<endl;
    return 0;
}

F. Little red 375

Title: Portal

Meaning: give a number with a length of 300000 bits, rearrange its bits so that the rearranged number can be divided by 375, output the rearranged number (excluding the leading 0), otherwise - 1;

Problem solving idea: 375 can be divided into 3 * 125, that is, the number after rearrangement should be a multiple of 3 and 125 at the same time. Note that the number of digits is too large;

For 3, it is very simple. If the sum of each digit can be divided by 3, then the number can also be divided by 3;

The characteristic of 125125 is that a cycle of 125 is 1000, which simply means enumerating the multiples of 125 in three digits. If the last three digits of a number are multiples of 125, the number can be divided by 125; the enumeration method can be stored in a bucket to see whether the remaining numbers in the bucket can form multiples of 125 in three digits (note that the leading 0 is considered);

AC Code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

typedef long long ll;

int st[50];

// string check[8] = {"125", "250", "375", "500", "625", "750", "875", "000"};
string check[8]={"500","000","750","250","125","375","625","875"};//Here, the ending of 0 is put in front to prevent leading 0;
int main()
{
    string s;
    cin>>s;
    int len = s.length();
    ll ans = 0;
    for(int i = 0; i<len; i++){
        st[s[i] - '0']++;
        ans += s[i] - '0';
    }
    if(ans%3!=0){
        puts("-1");
        return 0;
    }
    for(int i = 0; i<8; i++){
        for(int j = 0; j<3; j++){
            st[check[i][j] - '0']--;
        }
        bool flag = 1;
        for(int j = 0; j<=9; j++){
            if(st[j]<0){
                flag = 0;
                break;
            }
        }
        if(flag){
            for(int j=9;j>=0;j--)while(st[j])printf("%d", j),st[j]--;
            cout<<check[i];
            return 0;
        }
        for(int j = 0; j<3; j++){
            st[check[i][j] - '0']++;
        }
    }
    puts("-1");
    return 0;
}

Posted by ineedhelp on Sun, 05 Dec 2021 00:29:12 -0800