Codeforces Round #632 (Div. 2) 题解

A. Little Artem

  • 题意
    你需要绘制一个 n × m n\times m n×m的木板,木板中的单元格要么是白色要么是黑色的。现在定义 B B B的值为黑色单元格相邻的单元格至少有一个是白色的数量,同理 W W W的值定义为白色单元格相邻的单元格至少有一个是黑色的数量。你需要保证 B = W + 1 B=W+1 B=W+1

  • 解题思路
    这种题一般需要针对性的解决,即对于任何的 n × m n\times m n×m都适用,我们试想,如果绘制一个白块,那么 W W W就一定为 1 1 1,我们需要让 B = 2 B=2 B=2,这也很好办,直接放到四个对角任意一个,那么与之相邻的黑块就有两个。符合要求。

  • AC代码

/**
  *@filename:A
  *@author: pursuit
  *@created: 2021-08-10 18:18
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int t,n,m;
void solve(){
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= m; ++ j){
            if(i == n && j == m)cout << 'W';
            else cout << 'B';
        }
        cout << endl;
    }
}
int main(){	
    cin >> t;
    while(t -- ){
        cin >> n >> m;
        solve();
    }
    return 0;
}

B. Kind Anton

  • 题意
    给你一个序列 a , b a,b a,b。其中 a a a的初始值只有 { − 1 , 0 , 1 } \{-1,0,1\} {1,0,1},你可以选择 ( i , j ) (i,j) (i,j),其中 i < j i<j i<j。然后将 a i a_i ai加到 a j a_j aj上,需要你判断 a a a能否变成 b b b

  • 解题思路
    显然,我们只要在进行操作之前我们想要的 1 , − 1 1,-1 1,1,那么必然可行。即我们可以记录 1 1 1 − 1 -1 1是否出现过,然后遍历一遍数组,当需要用到的时候没有,那么此时必定不可行。至此题解。

  • AC代码

/**
  *@filename:B
  *@author: pursuit
  *@created: 2021-08-10 18:35
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int t,n,a[N],b[N];
void solve(){
    bool flag = false;
    int cnt1 = 0,cnt2 = 0;
    for(int i = 1; i <= n; ++ i){
        if(a[i] == b[i]){
        }
        else if(a[i] < b[i] && cnt1 == 0){
            flag = true;
            break;
        }
        else if(a[i] > b[i] && cnt2 == 0){
            flag = true;
            break;
        }
        if(a[i] == 1)cnt1 ++;
        else if(a[i] == -1)cnt2 ++;
    }
    if(flag){
        cout << "NO" << endl;
    }
    else{
        cout << "YES" << endl;
    }
}
int main(){	
    cin >> t;
    while(t -- ){
        cin >> n;
        for(int i = 1; i <= n; ++ i){
            cin >> a[i];
        }
        for(int i = 1; i <= n; ++ i){
            cin >> b[i];
        }
        solve();
    }
    return 0;
}

C. Eugene and an array

  • 题意
    给你一个数组,需要你找到非空好子数组的数量。其中好子数组定义为:其任意子数组元素总和不为 0 0 0

  • 解题思路
    由前缀和易知,如果一段区间 [ l , r ] [l,r] [l,r] 0 0 0,那么 s u m [ r ] − s u m [ l − 1 ] = 0 sum[r] - sum[l-1]=0 sum[r]sum[l1]=0,所以我们可以利用记录前缀和的位置 i i i,那么在过程中维护区间和不为 0 0 0的长度即可,累加符合区间数量即可。

  • AC代码

/**
  *@filename:C
  *@author: pursuit
  *@created: 2021-08-10 18:45
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 2e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,a[N];
map<ll,int> p;
void solve(){
    ll ans = 0, sum = 0;
    int pos = -1;//为最早不好的。
    p[0] = 0;
    for(int i = 1; i <= n; ++ i){
        sum += a[i];
        if(p.count(sum)){
            pos = max(pos,p[sum]);
        }
        ans += i - (pos + 1);
        p[sum] = i;
    }
    cout << ans << endl;
}
int main(){	
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &a[i]);
    }
    solve();
    return 0;
}

D. Challenges in school №41

  • 题意
    给定序列求使得转身 k k k轮刚好序列中不再存在转身的序列的解决方案。

  • 解题思路
    我们可以将每一轮左转的人存储起来。然后判断轮数够不够,如果不够,判断我们能不能分解构成 k k k轮。最后输出解决方案的时候要注意每一轮每一轮输出,注意按顺序填充我们的轮次。

  • AC代码

/**
  *@filename:D
  *@author: pursuit
  *@created: 2021-08-11 10:22
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,k,a[N];
char s[N];
vector<vector<int> > ans;
void solve(){
    //将每轮左转的存入数组中。
    int sum = 0;
    while(true){
        vector<int> now;
        for(int i = 1; i < n; ++ i){
            if(a[i] && !a[i + 1]){
                now.push_back(i);
                //debug(i);
                swap(a[i],a[i + 1]);
                i ++;
            }
        }
        //判断是否还存在转身的。
        if(now.empty())break;
        sum += now.size();//转身对数。
        ans.push_back(now);
    }
    //由于需要使得序列中转身k轮后且恰好不出现转身的序列。
    //若sum > k我们可以填充。
    if(ans.size() > k || sum < k){
        puts("-1");
    }
    else{
        int res = k - ans.size();//需要填充的轮次。
        for(auto now : ans){
            while(now.size() > 1 && res > 0){
                printf("1 %d\n", now.back());
                now.pop_back();
                res --;
            }
            printf("%d ", now.size());
            for(auto x : now){
                printf("%d ", x);
            }
            puts("");
        }
    }
}
int main(){	
    scanf("%d%d", &n, &k);
    scanf("%s", s + 1);
    for(int i = 1; i <= n; ++ i){
        if(s[i] == 'R')a[i] = 1;
    }
    solve();
    return 0;
}

E. Road to 1600

  • 题意
    找到一种方案,使得车花费比皇后的花费要多。

  • 解题思路
    显然,当 n < 3 n < 3 n<3时是不存在的,因为皇后畅通无阻,试想,当 n = 3 n=3 n=3时,我们可以手撕一种方案,注意我们需要让 1 1 1在边界。这样我们就可以将 1 1 1看成入口,然后对于 n > 3 n>3 n>3的时候,环该方案构造即可。
    在这里插入图片描述

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@created: 2021-08-11 10:58
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 500 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

//找到3 * 3矩阵的特例,再从1入口进去即可。
int n,res[N][N];
void solve(){
    if(n <= 2){
        puts("-1");
    }
    else{
        res[1][1] = 9,res[1][2] = 5,res[1][3] = 6;
        res[2][1] = 7,res[2][2] = 2,res[2][3] = 8;
        res[3][1] = 1,res[3][2] = 3,res[3][3] = 4;
        int t = n,num = 0;//num为编号。
        while(t > 3){
            if(t % 2 == 0){
                for(int i = 1; i <= t; ++ i){
                    res[i][t] = ++ num;
                }
                for(int j = t - 1; j >= 1; -- j){
                    res[t][j] = ++ num;
                }
            }
            else{
                for(int j = 1; j <= t; ++ j){
                    res[t][j] = ++ num;
                }
                for(int i = t - 1; i >= 1; -- i){
                    res[i][t] = ++ num;
                }
            }
            t --;
        }
        //最后编号为num。
        for(int i = 1; i <= n; ++ i){
            for(int j = 1; j <= n; ++ j){
                if(i <= 3 && j <= 3)res[i][j] += num;
                printf("%d ", res[i][j]);
            }
            puts("");
        }
    }
}
int main(){	
    scanf("%d", &n);
    solve();
    return 0;
}

F. Kate and imperfection

  • 题意
    求当 k = [ 2 , n ] k=[2,n] k=[2,n]时, k k k a a a序列大小,使得 a a a序列中任意两元素的 g c d gcd gcd最大值最小。

  • 解题思路
    我们自然是想将质数的放入进去,然后再按除本身的最大因子从小到达放入即可达到最优。那么只需要记录每个数的次大因子,当该数放入时,结果就为 它 它

  • AC代码

/**
  *@filename:F
  *@author: pursuit
  *@created: 2021-08-11 10:42
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n;
void solve(){
    vector<int> ans(n + 1,1);//先定义所有的因子都为1.
    for(int i = 2; i <= n; ++ i){
        for(int j = i * 2; j <= n; j += i){
            //将i的倍数都找出来。
            ans[j] = i;
        }
    }
    sort(ans.begin(),ans.end());
    for(int i = 2; i <= n; ++ i){
        printf("%d%c", ans[i], i == n ? '\n' : ' ');
    }
}
int main(){	
    scanf("%d", &n);
    solve();
    return 0;
}
posted @ 2022-03-26 16:48  unique_pursuit  阅读(39)  评论(0)    收藏  举报