A
题意:找到最大的不含零且没有连续的两位相同的十进制整数,满足每一位之和为 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
题意:对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
题意:n*m 网格,一次可以选择一个矩形区域然后进行“棋盘染色”。棋盘染色说的是,左上角为白色,相邻格子的颜色相反。请构造方案从空白局面染成给定局面或报告无解。
注意到这种染色问题,后涂的色会覆盖掉前涂的色。
分析:
1.每次选定一个矩形,其左上角一定得染成白色(0),可以推出目标图形的(1,1)单元格一定得是 0(因为如果一个矩形包含该单元格,则该单元格一定是左上角的那个);
2.为了仅把该染成黑色的格子(减少对其他格子的影响,从而保证一定能染成目标图)
则推出应该按照 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;
}