Codeforces Round #956 (Div. 2)A-C解题报告

A. Array Divisibility

Problem - A - Codeforces

题目类型:构造。

解题思路:每个数都是自己因数的倍数,所以直接构造a[i]=i。

AC代码:

#include<iostream>

using namespace std;

void solve()
{
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		cout<<i<<' ';
	}
	cout<<'\n';
}

int main()
{
	int t;cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

B. Corner Twist

Problem - B - Codeforces

题目类型:构造,贪心。

解题思路:(暴力)从左上向右下(不含右边界和下边界)遍历,取正方形四个对角为a[i][j],a[i][j+1],a[i+1][j],a[i+1][j+1],贪心的将每个a[i][j]变成b[i][j]。最后遍历右边界和下边界,若a[i][j]!=b[i][j]则输出"NO"。

AC代码:

#include<iostream>

using namespace std;

const int N=510;
char a[N][N],b[N][N];

void solve(){
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%s",a[i]+1);
	} 
	for(int i=1;i<=n;i++){
		scanf("%s",b[i]+1);
	} 
	//贪心 
	for(int i=1;i<n;i++){
		for(int j=1;j<m;j++){
			if(a[i][j]!=b[i][j]){
				int k=(b[i][j]-a[i][j]+3)%3;
				a[i][j]=(a[i][j]-'0'+k)%3+'0';
				a[i+1][j+1]=(a[i+1][j+1]-'0'+k)%3+'0';
				a[i+1][j]=(a[i+1][j]-'0'+3-k)%3+'0';
				a[i][j+1]=(a[i][j+1]-'0'+3-k)%3+'0';
			}
		}
	}
	//检验右边界和下边界 
	for(int i=1;i<=n;i++){
		if(a[i][m]!=b[i][m]){
			cout<<"NO\n";
			return;
		}
	}
	for(int i=1;i<=m;i++){
		if(a[n][i]!=b[n][i]){
			cout<<"NO\n";
			return;
		} 
	} 
	cout<<"YES\n";
}

int main()
{
	int t;cin>>t;
	while(t--){
		solve();
	}
	return 0;
 } 

C. Have Your Cake and Eat It Too

Problem - C - Codeforces

题目类型:贪心,前缀和,暴力。

解题思路:

1.求出a,b,c三个数组的前缀和与后缀和,以及t=\left \lceil tot/3 \right \rceil

2.分类讨论(条件成立则输出答案)

①左分界点为a的前缀和大于t,右分界点为b的后缀和大于t,判断左右分界点之间c数组元素之和是否大于t;

②左分界点为a的前缀和大于t,右分界点为c的后缀和大于t,判断左右分界点之间b数组元素之和是否大于t;

③左分界点为b的前缀和大于t,右分界点为a的后缀和大于t,判断左右分界点之间c数组元素之和是否大于t;

④左分界点为b的前缀和大于t,右分界点为c的后缀和大于t,判断左右分界点之间a数组元素之和是否大于t; 

⑤左分界点为c的前缀和大于t,右分界点为a的后缀和大于t,判断左右分界点之间b数组元素之和是否大于t;

⑥左分界点为c的前缀和大于t,右分界点为b的后缀和大于t,判断左右分界点之间a数组元素之和是否大于t。

3.都不成立则输出-1。

AC代码:

#include<iostream>
#include<cstring>

using namespace std;

typedef long long LL;
const int N=200010;

int a[N],b[N],c[N];
//前缀和 
LL pa[N],pb[N],pc[N];
//后缀和 
LL sa[N],sb[N],sc[N];
//整除3向上取整 
LL divup(LL x){
	if(x%3==0){
		return x/3;
	}
	else{
		return x/3+1;
	}
}

void solve(){
	int n;cin>>n;
	//初始化后缀和数组防止上一组数据干扰 
	memset(sa,0,sizeof sa);
	memset(sb,0,sizeof sb);
	memset(sc,0,sizeof sc);
	//求前缀和 and 后缀和 
	for(int i=1;i<=n;i++){
		cin>>a[i];
		pa[i]=pa[i-1]+a[i]; 
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
		pb[i]=pb[i-1]+b[i];
	}
	for(int i=1;i<=n;i++){
		cin>>c[i];
		pc[i]=pc[i-1]+c[i];
	}
	for(int i=n;i>=1;i--){
		sa[i]=sa[i+1]+a[i];
	}
	for(int i=n;i>=1;i--){
		sb[i]=sb[i+1]+b[i];
	}
	for(int i=n;i>=1;i--){
		sc[i]=sc[i+1]+c[i];
	}
	
	//求tot/3 
	LL t=divup(pa[n]);
	bool f1=1,f2=1,f3=1;
	
	//分类讨论分界点情况 
	for(int i=1;i<=n;i++){
		if(f1 && pa[i]>=t){
			for(int j=n;j>=1;j--){
				if(sb[j]>=t){
					if(pc[n]-pc[i]-sc[j]>=t){
						cout<<1<<' '<<i<<' '<<j<<' '<<n<<' '<<i+1<<' '<<j-1<<'\n';
						return;
					}
				}
			}
			for(int j=n;j>=1;j--){
				if(sc[j]>=t){
					if(pb[n]-pb[i]-sb[j]>=t){
						cout<<1<<' '<<i<<' '<<i+1<<' '<<j-1<<' '<<j<<' '<<n<<'\n';
						return;
					}
				}
			}
			f1=0;
		}
		if(f2 && pb[i]>=t){
			for(int j=n;j>=1;j--){
				if(sa[j]>=t){
					if(pc[n]-pc[i]-sc[j]>=t){
						cout<<j<<' '<<n<<' '<<1<<' '<<i<<' '<<i+1<<' '<<j-1<<'\n';
						return;
					}
				}
			}
			for(int j=n;j>=1;j--){
				if(sc[j]>=t){
					if(pa[n]-pa[i]-sa[j]>=t){
						cout<<i+1<<' '<<j-1<<' '<<1<<' '<<i<<' '<<j<<' '<<n<<'\n';
						return;
					}
				}
			}
			f2=0;
		}
		if(f3 && pc[i]>=t){
			for(int j=n;j>=1;j--){
				if(sa[j]>=t){
					if(pb[n]-pb[i]-sb[j]>=t){
						cout<<j<<' '<<n<<' '<<i+1<<' '<<j-1<<' '<<1<<' '<<i<<'\n';
						return;
					}
				}
			}
			for(int j=n;j>=1;j--){
				if(sb[j]>=t){
					if(pa[n]-pa[i]-sa[j]>=t){
						cout<<i+1<<' '<<j-1<<' '<<j<<' '<<n<<' '<<1<<' '<<i<<'\n';
						return;
					}
				}
			}
			f3=0;
		}
	}
	//impossible输出-1 
	cout<<-1<<'\n';
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值