Codeforces Round #777 (Div. 2) A-D题解

A

Problem - A - Codeforces

题意:找到最大的不含零且没有连续的两位相同的十进制整数,满足每一位之和为 n。

分析:因为要找到最大的数,所以我们可以让答案中的每位上的数尽可能的小(位数变多)

,1为除0外最小的数,但是因为相邻的两个数字不能相同,所以需要再取一个除1最小的数,即2

答案最后由 1和2组成. 确定数字的顺序,即确定第一个数字:可以通过n%3(1+2)判断

(看看最后剩的是哪个数,多的那个数确定了第一个数,因为相同数字不能相邻)

当余数为 1,即只能以1开头

当余数为0/2,只能以2开头

1,2交替排列构成最大答案.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+100;
const int mod=1e9+7;
typedef pair<int,int> PII; 
#define x first
#define y second
#define pb push_back
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int n;
 
 
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        if(n%3==1)
        {
            int cnt=1;
            for(int i=n;i;cnt++)
            {
                if(cnt&1)
                {
                    cout<<"1";
                    i--;
                }
                else
                {
                    cout<<"2";
                    i-=2;
                }
 
            }
            cout<<endl;
 
        }
        else
        {
            int cnt=1;
 
            for(int i=n;i;cnt++)
            {
                if(cnt&1)
                {
                    cout<<"2";
                    i-=2;
                }
                else
                {
                    cout<<"1";
                    i-=1;
                }
 
            }
            cout<<endl;
 
        }
 
 
    }
 
 
    return 0;
}
 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+100;
typedef pair<int,int> PII; 
#define x first
#define y second
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

int main() {
    int T; 
   cin>>T;
    while (T--) {
        int n; 
        cin>>n;
        if (n % 3 == 1) {
            --n; putchar('1');
        }
        for (int i = 0; n; i ^= 1) {                //异或实现交替输出
            if (!i) n -= 2, putchar('2');
            else --n, putchar('1');
        }
        putchar('\n');
    }
    return 0;
}

B

Problem - B - Codeforces

题意:对01矩阵,询问其中是否有两个极大的仅由1组成的子矩阵,使得两矩阵有重复格子.

有则输出no.否则反之.

分析:通过观察,若出现构不成矩形的全部都是1的连通块,再进一步若出现上述情况,则一定出现在4*4的方格中1的个数为3.

BFS 判断是否出现 构不成矩形的全部都是1的连通块.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+100;
const int mod=1e9+7;
typedef pair<int,int> PII; 
#define x first
#define y second
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
char a[105][105];
int n,m;
 int maxx=-1,minx=1e9,miny=1e9,maxy=-1,ans;
 void bfs(int x,int y)       //注意bfs的floodfill算法的1更改为0的情况,不能只在while里面写
 {                           //  a[x][y]='0';
     queue<PII> q;
     q.push({x,y});
     a[x][y]='0';
     while(q.size())
     {
         auto t=q.front();
         q.pop();
           
            ans++;
            maxx=max(maxx,t.x);
            minx=min(minx,t.x);
            maxy=max(maxy,t.y);
            miny=min(miny,t.y);
         for(int i=0;i<4;i++)
         {
            int xx=t.x+dx[i],yy=t.y+dy[i];
            if(xx<1||xx>n||yy<1||yy>m)
            continue;
            
            if(a[xx][yy]=='1')
            {
                a[xx][yy]='0';
                q.push({xx,yy});
            }
         }
     }

 }
int main()
{
    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 f=0;

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]=='1')
                {
                    ans=0;
                    maxx=-1,minx=1e9,miny=1e9,maxy=-1;
                    bfs(i,j);
        
                    if(ans!=(maxx-minx+1)*(maxy-miny+1))
                    {
                        cout<<"no"<<endl;
                        f=1;
                        break;
                    }
                }
            }
            if(f==1)
            break;
        }
        if(!f) cout<<"yes"<<endl;
        

    }
  
    return 0;
}

循环判断:4*4的方格中1的个数为3.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+100;
const int mod=1e9+7;
typedef pair<int,int> PII; 
#define x first
#define y second
#define pb push_back
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

int main()
{
	int n, m; 
    cin>>n>>m; 
	string a[n+1]; 
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<n-1;i++) for(int j=0;j<m-1;j++)
	{
	    if(a[i][j]-'0'+a[i+1][j]-'0'+a[i][j+1]-'0'+a[i+1][j+1]-'0' == 3) 
	    {
	        cout<<"NO\n";
	        return;
	    }
	}
	cout<<"YES\n";


    return 0;
}


C

Problem - C - Codeforces

题意:n*m 网格,一次可以选择一个矩形区域然后进行“棋盘染色”。棋盘染色说的是,左上角为白色,相邻格子的颜色相反。请构造方案从空白局面染成给定局面或报告无解。

注意到这种染色问题,后涂的色会覆盖掉前涂的色。

分析:

1.每次选定一个矩形,其左上角一定得染成白色(0),可以推出目标图形的(1,1)单元格一定得是 0(因为如果一个矩形包含该单元格,则该单元格一定是左上角的那个);

2.为了把该染成黑色的格子(减少对其他格子的影响,从而保证一定能染成目标图)

则推出应该按照 0 1 或者 \binom{0}{1}这样染色,(只能以0开头,因为左上角必须是0)

3.注意到这种染色问题,后涂的色会覆盖掉前涂的色。可以推出应该从最后一个格子倒着涂色.

(本质还是推论2,因为如果从第一个开始染色,则会把之前涂好的黑色染成白色)

例如 会把(2,1)和(4,3)格子重新变为0

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+100;
typedef pair<int,int> PII; 
#define x first
#define y second
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
char a[105][105];
int n,m;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
        cin>>a[i];
        if(a[0][0]=='1') 
        {
            cout<<"-1"<<endl;
            continue;
        }
        
        vector<array<int,4>> ans;
        for(int i=n-1;i>=0;i--)
        {
            for(int j=m-1;j>=0;j--)
            {
                if(a[i][j]=='0') continue;
                
                if(j!=0)
                ans.push_back({i,j-1,i,j});
                else
                ans.push_back({i-1,j,i,j});        
            }
        }
        cout<<ans.size()<<endl;
        for(auto [x1,y1,x2,y2]:ans)
        cout<<x1+1<<" "<<y1+1<<" "<<x2+1<<" "<<y2+1<<endl;
    }


    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值