Loading

Codeforces Round #777 (Div. 2)

先吐槽一句,怎么会有人出阅读理解+分类讨论题啊。。。

A

给出一个数 \(n\),让你构造一个最大的数,使得这个数各位数字之和为 \(n\) 且不含 \(0\) 也没有两个相同的数相邻。那直接构造 \(12\) 交替就行了,分类一下模 \(3\) 的余数然后直接输出就行啦。

My Code
using namespace std;
void solve(){
	int n;cin>>n;
	if(n%3==0){
		rep(i,1,n/3) cout<<"21";
		cout<<'\n';
	}else if(n%3==1){
		cout<<"1";
		rep(i,1,n/3) cout<<"21";
		cout<<'\n';
	}else{
		cout<<"2";
		rep(i,1,n/3) cout<<"12";
		cout<<'\n';
	}
}
int main()
{
	ios::sync_with_stdio(0);
	int T;
	for(cin>>T;T--;)
		solve();
	return 0;
}

B

定义一个子矩阵是好的,当且仅当这个子矩阵内全是 \(1\) 并且不被其它任意一个全是 \(1\) 的矩阵包含。

定义一个矩阵是优雅的,当且仅当没有两个好的矩阵相交。

判断矩阵是不是好的。

考虑一个 \(2\times 2\) 的子矩阵内,如果 \(1\) 的个数是 \(4\) 的(也就是满的),那这一定只被一个好的矩阵包含。同样的只有 \(2\) 及以下个点也只能被一个好的矩阵包含(要不然就被最大的好的矩阵包含它就不好了)。但是如果是 \(3\) 的话,那在拐弯的地方那个格子会被包含 \(2\) 次。

所以扫一遍有没有 \(2\times 2\) 的矩阵内有 \(3\) 个 \(1\) 的。

My Code
using namespace std;
const int MAXN=110;
char mp[MAXN][MAXN];
void solve(){
	int n,m;cin>>n>>m;
	rep(i,1,n) rep(j,1,m) cin>>mp[i][j];
	rep(i,1,n-1) rep(j,1,m-1){
		int cnt=mp[i][j]-'0'+mp[i+1][j]-'0'+mp[i][j+1]-'0'+mp[i+1][j+1]-'0';
		if(cnt==3){
			cout<<"NO\n";
			return;
		}
	}cout<<"YES\n";
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;for(cin>>T;T--;)
		solve();
	return 0;
}

C

每次可以选中一个子矩阵,并将其黑白染色(左上是白)。最初是空白的矩阵,求构造方案使得达到最终状态。

构造,我们能让任意的 \((x,y+1)\) 或者 \((x+1,y)\) 变成黑色并且不对别的产生影响,那只要判断一下 \((1,1)\) 是否是黑的,然后倒着填,每次填一个黑色格子就行了。

My Code
using namespace std;
const int MAXN=110;
struct opt{
	int lx,ly,rx,ry;
};
int a[MAXN][MAXN],cur[MAXN][MAXN];
void solve(){
	int n,m;cin>>n>>m;char c;
	rep(i,1,n) rep(j,1,m) cin>>c,a[i][j]=c-'0',cur[i][j]=0;
	if(a[1][1]){cout<<-1<<'\n';return;}
	vector<opt> ans;
	per(i,n,1) per(j,m,1){
		if(cur[i][j]==a[i][j]) continue;
		if(!a[i][j])
			cur[i][j]=0,ans.pb((opt){i,j,i,j});
		else{
			if(j>1) cur[i][j]=1,cur[i][j-1]=0,ans.pb((opt){i,j-1,i,j});
			else cur[i-1][j]=0,cur[i][j]=1,ans.pb((opt){i-1,j,i,j});
		}
	}cout<<(int)ans.size()<<'\n';
	for(auto s:ans) cout<<s.lx<<' '<<s.ly<<' '<<s.rx<<' '<<s.ry<<'\n';
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;for(cin>>T;T--;)
		solve();
	return 0;
}

D

定义一个数是好数,当且仅当 \(d|a\) 且 \(d^2\nmid a\)。定义一个数是牛逼的当且仅当这个数有至少两种分解因数的方式,使得分解出来的都是好数。

求给出 \(x,d\) 后 \(x\) 是不是牛逼的。

令 \(x=kd^n\),\(n\) 取最大。然后开始分讨。(下面每个如果都在上面的如果不成立的前提下)

如果 \(n\le1\),那么显然不行。
如果 \(k\) 是合数,那么显然可以。
如果 \(d\) 是质数,那么显然不行。
如果 \(n<3\),那么显然不行。
如果 \(n>3\),那么显然可以。(就你随便拆一个 \(d\) 就行了)
如果 \(n=3\),那么把最后一个 \(d\) 拆开,枚举所有拆法,然后直接判断就行了。

My Code
#define int long long
using namespace std;
bool isp(int x){
	if(x==1) return 1;
	for(int i=2;i*i<=x;i++)
		if(x%i==0) return 0;
	return 1;
}
void solve(){
	int x,d;cin>>x>>d;
	int n=0;while(x%d==0) x/=d,n++;
	if(n<2){cout<<"NO\n";return;}
	if(!isp(x)){cout<<"YES\n";return;}
	if(isp(d)){cout<<"NO\n";return;}
	if(n>3){cout<<"YES\n";return;}
	if(n<=2){cout<<"NO\n";return;}
	for(int i=2;i*i<=d;i++){
		if(d%i) continue;
		int a=i,b=d/i;
		if(x*a%d){
			cout<<"YES\n";
			return;
		}
		if(x*b%d){
			cout<<"YES\n";
			return;
		}
	}cout<<"NO\n";
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;for(cin>>T;T--;)
		solve();
	return 0;
}

E

F

posted @ 2022-03-12 08:30  ZCETHAN  阅读(173)  评论(0)    收藏  举报