2020-06-01 — 习题训练四题解

https://vjudge.net/contest/376443#overview

A-Dreamoon and Ranking Collection

给x个补丁,从第一个开始补, 遇见漏洞,补丁就少一个, 补完之后,从一到最大的没毛病的数是多少

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

template <typename T>

inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
void solve(){
        
    int n, x, v;
    read(n), read(x);
    vector<int> a(n+1);
    vector<bool> s(300);
    
    for(int i = 1;i <= n; ++ i){
        read(a[i]);
        s[a[i]] = true;
    }
    for(int i = 1;i <= 300; ++ i){
        if(!s[i] && x > 0){
            x --;
            continue;
        }
        if(!s[i] && !x){
            v = i - 1;
            break;
        }
    }
    printf("%d\n", v);
}
int main()
{
    ios_base::sync_with_stdio(false);
    int t;
    read(t);
    while(t--) solve();
}

B - Dreamoon Likes Permutations

给一个序列,切开,使得切开后的两个序列中的数字为从1到该序列的长度(数字不能重复),求所有满足题意的切法 

用一个数组标记前面满足条件的序列,另一个标记后面满足条件的序列,最后输出。(借鉴某大佬)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

template <typename T>

inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
void solve(){
        
            
    int n, cnt = 0;
    read(n);
//    int a[n+1], cntl[n+1], cntr[n+1];
//    bool l[n+1], r[n+1];    
    vector<int> a(n+1), cntl(n+1), cntr(n+1);
    vector<bool> l(n+1), r(n+1);
    for(int i = 1;i <= n; ++ i) 
        read(a[i]);
    int x = 1;
    for(int i = 1;i <= n; ++ i){
        cntl[a[i]] ++;
        if(cntl[a[i]] >= 2) break;
        
        while(cntl[x] == 1 && x <= i) x ++; // 若是到不了i ,从x 到i 之间有0,也就不合适.
        if(x - 1 == i)
         l[i] = true;  
    }
    x = 1;
    for(int i = n;i >= 1; -- i){
        cntr[a[i]] ++;
        if(cntr[a[i]] >= 2) break;
        
        while(cntr[x] == 1 && x <= n - i + 1) x ++;
        if(x - 1 == n - i + 1) r[i] = true;
    }
    
    for(int i = 1;i <= n-1; ++ i)
        if(l[i] && r[i+1]) cnt ++;
    printf("%d\n", cnt);
    if(cnt)
    for(int i = 1;i < n; ++ i)
        if(l[i] && r[i + 1])
            printf("%d %d\n", i, n - i);
    
}    

int main()
{
    ios_base::sync_with_stdio(false);
    int t;
    read(t);
    while(t--) solve();
}

C - Exercising Walk

大概分类讨论吧

#include<iostream>
using namespace std;
int t, a, b, c, d, x, y, xl, xr, yl,yr;

int main()
{
    cin >> t;
    while (t--)
    {
        int flag = 0;
        cin >> a >> b >> c >> d;
        cin >> x >> y >> xl >> yl >> xr >> yr;
        //特判两种特殊情况
        if (xl == xr && (a >= 1 || b >= 1))
            flag = 0;
        else if(yl == yr && (c >= 1 || d >= 1))
            flag = 0;
        //判断是否在边界内
        else
        {
            x = x + (b - a);
            y = y + (d - c);
            if (x >= xl && x <= xr && y >= yl && y <= yr)
            flag = 1;
        }
        if (flag)
            cout << "YES" << endl;
        else 
            cout << "NO" << endl;
    }
    return 0;
}

 

D-Composite Coloring

 题意:给定n个合数,用m(<= 11) 种颜色染色,当两个数字有相同的公约数时可以染同一种颜色

找出前11个质数,若公约数相同,染同样颜色,不同就换颜色。题目给出 m<= 11 即可。而a < 1000, 所以不会 出现  37 * 43 这样的数, 也就是说,前11个质数够用(第十一个质数为31) (借鉴某大佬)

 

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

template <typename T>

inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
int gcd(int a, int b)
{
    while(b != 0)
    {
        int r = b;
        b = a % b;
        a = r;
    }
    return a;
}
void solve(){
        
    int prime[11] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
    int n, cnt = 0;
    read(n);
    vector<int> a(n+1), ans(n+1);
    map<int, int> dis;
    for(int i = 1;i <= n; ++ i) read(a[i]);
    
    for(int i = 1;i <= n; ++ i){
        for(int j = 0;j < 11; ++ j){
            if(a[i] % prime[j] == 0){
                if(!dis[prime[j]]) dis[prime[j]] = ++ cnt;
                ans[i] = dis[prime[j]];
                break;
            }
        }
    }
    printf("%d\n", cnt);
    for(int i = 1;i <= n; ++ i)
        printf("%d ",ans[i]);
    puts("");
}
int main()
{
    ios_base::sync_with_stdio(false);
    int t;
    read(t);
    while(t--) solve();
}

E - K-th Beautiful String

 

 

给出字符串aaaaaaaabb (类似) , 经过排列变换后,找出第 k 大的字符串(字典序)

n - 2  个a:  a a a a ... a a a   , 两个b 插进去;

第一个b 的位置 b = n - 1  :  a a a a ..... a a a b           k的可能取值为 1;

   b 的位置 b = n - 2  :  a a a a ..... a a b a          k :                      2  3 // 与不同的k 对应的另一个 b的位置应该能直接看出来

        b = n - 3      :a a a a ..... a b a a           k:                      4 5 6 

          。            k :         7 8 9 10

          。            

          。         

   b = 0         :   b a a a  .... a a a a             k :         i * ( i - 1) / 2 + 1    ....... ; (就当 i 从 1 开始自增好了)

现在可以回答第k 个是哪个了, 首先找到 k 所在的行,就可以找到第一个b的位置了,然后用 k 减去 所在行的第一个数,就是另一个b与n-1的距离,两个b的位置就找到了

//好麻烦,附个简洁的题解

https://blog.csdn.net/mrcrack/article/details/105133833?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

template <typename T>

inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}void solve(){
        
    int n, x;
    read(n), read(x);
    vector<char> a(n+1);
    for(int i = 1;i <= n - 2; ++ i) a[i] = 'a';
    int b1, b2;
    for(int i = 1;i <= n; ++ i){
        if((ll)i *(i - 1) / 2 + 1 > x){
            b1 = i-1;
            b1 = n - 1 - b1;
            b2 = x - ((ll) (i-1) * (i - 2) / 2 + 1);
            b2 = n - 2 - b2;
            break;
        }
    }
    for(int i = 0;i <= n-2; ++ i){
        if(i)
        putchar(a[i]);
        if(b1 == i) putchar('b');
        if(b2 == i) putchar('b');
    }
    puts("");        
}
int main()
{
    ios_base::sync_with_stdio(false);
    int t;
    read(t);
    while(t--) solve();
}

 F - Carousel

题意: 闭合圈中,相邻的不同元素要涂成不同颜色,问最多需要多少种颜色可涂满,并写出涂法

闭合圈中,有一种元素时,全输出1

有两种元素时,循环输出1, 2;
有三种元素时, 如果 n 为偶数, 循环输出1, 2;

       如果n 为奇数, 查找有无相邻相等的元素(闭合圈),如果有那就可以看成偶数列,第一次相等时, 相等的两个元素输出一样的数,这样就又可以看成偶数列了;

                                  如果没有相邻相等的,那就循环输出1, 2最后一个元素输出3

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

template <typename T>

inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
void solve(){
    
    int n, flag = 0;
    read(n);
    vector<int> a(n+1), ans(n+1);
    set<int> st;
    for(int i = 1;i <= n; ++ i){
        read(a[i]);
        if(i > 1 && a[i] == a[i-1])
            flag ++;
        if(i == n && a[i] == a[1])
            flag ++;
    }
//    cout << "flag : " << flag << endl; 
    if(flag == n){
        puts("1");
        for(int i = 1;i <= n; ++ i)
            printf("1 ");
        puts("");
        return ;
    }
    if(n % 2 == 0){
        puts("2");
        for(int i = 1;i <= n / 2; ++ i){
            printf("1 2 ");
        }
        puts("");
        return ;
    }
    else{
        if(flag == 0){
            puts("3");
            for(int i = 1;i <= n / 2; ++ i)
                printf("1 2 ");
            puts("3");
            return ;
        }
        else{
            flag = 1;
            puts("2");
            int cnt = 1;
            for(int i = 1;i <= n; ++ i){
                if(cnt > 2) cnt = 1;
                if(i > 1 && a[i] == a[i-1] && flag){ //补一次就行 
                    ans[i] = ans[i-1];
                    cnt = ans[i-1];
                    flag = 0;
                }
                else
                ans[i] = cnt;
                cnt ++;
                printf("%d ",ans[i]);
            }
            puts("");
        }
    }


}
int main()
{
    ios_base::sync_with_stdio(false);
    int t;
    read(t);
    while(t--) solve();
}

 

posted @ 2020-06-02 21:09  IIlIlIlI  阅读(155)  评论(0编辑  收藏  举报