【记录CF】Codeforces Round #777 (Div. 2) A~C 题解

目录

杂谈

A. Madoka and Math Dad

B. Madoka and the Elegant Gift

C. Madoka and Childish Pranks


杂谈

又是一场离谱掉分场(;´д`)ゞ,AB题就跟脑子宕机了一样。

A题一开始分类就分错了,按奇偶分,过了样例,自信满满地交了一发,TLE,又试了个例子,发现不对,死循环了......后来反应过来,AC时已经18分钟了......

B题觉得思路无懈可击,然后交了一发,WA3,然后以为是没有特判,又交了一发,还是WA3,最后发现判断函数里应该是 i < n 之类的,写成了 i <= n......

C题是这三题中最顺利的了,出了思路之后很快想到了代码实现,然后一波过了。

最近罚时有点严重,细节处理出现了挺多问题的,要多注意一些细节了(ノへ ̄、)。

A. Madoka and Math Dad

题目链接:Problem - A - Codeforces

题目大意:给定一个数 n 表示一个数的各个数位之和,要求该数不出现 0,且相邻两位数字不能相同,求这个数的最大值。

解题思路:要想让数最大,只能使用 1,2 两个数字,这样组成的数数位最长,根据 n 对 3 的余数可以分成三类:n % 3 == 0 时,需要按 21 的方式进行构造;n % 3 == 1 时,需要按 121 的方式构造;n % 3 == 2 时,需要按 212 的方式构造。

AC代码:

#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define mid (l + r >> 1)

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;

int main(){
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        if(n % 3 == 0){
            while(n){
                cout << 21;
                n -= 3;
            }
        }
        else if(n % 3 == 1){
            while(n > 1){
                cout << 12;
                n -= 3;
            }
            cout << 1;
        }
        else{
            while(n > 2){
                cout << 21;
                n -= 3;
            }
            cout << 2;
        }
        cout << endl;
    }
    return 0;
}

B. Madoka and the Elegant Gift

题目链接:Problem - B - Codeforces

题目大意:在给定的图中找只包含 1 的最大矩形,如果至少有两个最大矩形发生交叉,这个图就是不优美的,输出NO,反之就是优美的,输出YES。下图就是一个不优美的图。

解题思路:这里提供两种思路(第一种是我的思路,第二种是同学的思路),第一种是寻找 0 的位置,然后判断它的(左上、左、上)(右上、右、上)(左下、左、下)(右下、右、下)这四种情况是否存在一种都为 1,即构成 ”|_“ 的形状,如果有,那么这个图一定不优美。第二种是不管每个位置是 0 还是 1,遍历每个 2 * 2 的正方形,只要存在一个正方形中恰好 3 个点是 1,那么这个图一定不优美。

AC代码:

第一种:

#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define mid (l + r >> 1)

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
const int N = 105;
char a[N][N];
int n, m;

bool check(int i, int j){
    if(a[i][j] == '0'){
        if(i > 1 && j > 1 && a[i - 1][j - 1] == '1' && a[i - 1][j] == '1' && a[i][j - 1] == '1') return true;
        if(i > 1 && j < m && a[i - 1][j] == '1' && a[i - 1][j + 1] == '1' && a[i][j + 1] == '1') return true;
        if(i < n && j > 1 && a[i + 1][j - 1] == '1' && a[i][j - 1] == '1' && a[i + 1][j] == '1') return true;
        if(i < n && j < m && a[i + 1][j] == '1' && a[i + 1][j + 1] == '1' && a[i][j + 1] == '1') return true;
    }
    return false;
}

int main(){
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;
    while(t--){
        cin >> n >> m;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                cin >> a[i][j];
            }
        }
        int flag = 0;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(check(i, j)){
                    flag = 1;
                    break;
                }
            }
        }
        if(flag) cout << "NO" << endl;
        else cout << "YES" << endl;
    }
    return 0;
}

第二种:

#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define mid (l + r >> 1)

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
const int N = 105;
char a[N][N];
int n, m;

bool check(int i, int j){
    int cnt = 0;
    if(a[i][j] == '1') cnt++;
    if(a[i + 1][j] == '1') cnt++;
    if(a[i][j + 1] == '1') cnt++;
    if(a[i + 1][j + 1] == '1') cnt++;
    if(cnt == 3) return true;
    return false;
}

int main(){
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;
    while(t--){
        cin >> n >> m;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                cin >> a[i][j];
            }
        }
        int flag = 0;
        for(int i = 1; i < n; i++){
            for(int j = 1; j < m; j++){
                if(check(i, j)){
                    flag = 1;
                    break;
                }
            }
        }
        if(flag) cout << "NO" << endl;
        else cout << "YES" << endl;
    }
    return 0;
}

C. Madoka and Childish Pranks

题目链接:Problem - C - Codeforces

题目大意:给定一个棋盘(1代表黑,0代表白),问是否能按照题目所给的上色方式(如下图,可选任意矩形大小进行上色,但必须与图相同,即第一格为白色,相邻的均为黑色)得到该棋盘,如果能,则输出上色操作数,然后每行输出四个数代表上色区域的左上角坐标(x1, y1)和右下角坐标(x2, y2);如果不能则输出-1。

解题思路:构造题,要想到除了(1, 1)为黑色的棋盘,任意一个棋盘都可以由 1 * 2 或 2 * 1 的矩形上色方式进行上色得到。想到这个就好办了,只需要从下往上,从右往左进行上色,遇到 1 就进行一个 1 * 2 的上色,当遇到最左边出现 1 时,作一个 2 * 1 的上色,每次将答案存入 vector 就行了。

AC代码:

#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define mid (l + r >> 1)

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
const int N = 105;
char a[N][N];
int n, m;

vector<PII> ans;

int main(){
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;
    while(t--){
        cin >> n >> m;
        ans.clear();
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                cin >> a[i][j];
            }
        }
        if(a[1][1] == '1'){
            cout << -1 << endl;
            continue;
        }
        for(int i = n; i >= 1; i--){
            for(int j = m; j >= 1; j--){
                if(j == 1 && a[i][j] == '1'){
                    ans.push_back({i - 1, j});
                    ans.push_back({i, j});
                    continue;
                }
                if(a[i][j] == '1'){
                    ans.push_back({i, j - 1});
                    ans.push_back({i, j});
                }
            }
        }
        int len = ans.size();
        cout << len / 2 << endl;
        for(int i = 0; i < len; i += 2){
            cout << ans[i].first << ' ' << ans[i].second << ' ' << ans[i + 1].first << ' ' << ans[i + 1].second << endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值