上周比赛总结2021-12-04

比赛感想

上周周末因为补课的缘故没有参加比赛,今天集中了一下时间把比赛题重新做一下。
然后就发现,上周的比赛难度又上来了<苦笑>,提交榜也是惨不忍睹……

题目重现

Vasya and Golden Ticket

链接地址

题意:
本题给你n个数字,让你将这n个数字按顺序进行划分,至少划分为两堆,如果有任意一种划分方法使得每一堆的数字之和加起来相等,则输出yes,否则输出no

感受:
这是一道我做不出来的题……我能想到的方法只有暴力解题,把所有的可能枚举出来然后计算每种可能,这么干指定是超时要是真有一百个数字还不知道要跑几十秒呢……

解题思路:
大佬的思路就是厉害!
官方的本题解法就是:以第一堆为标准,首先给第一堆划分一个数,然后对后面的数字依次进行分堆并对每一堆求和,当该堆之和大于等于第一堆的数字之和之后则本堆划分完毕,对后续的数字进行同样的操作,同时每一次完成一堆的划分都将其与第一堆进行比较,对结果进行存储。第一次循环进行结束之后就开始给第一堆划分两个数,操作和上述相同。
最后统一整理,就得出了本题答案。

//代码实现
#include <iostream>
#include <string>

using namespace std;

int n;
string s;

int main() {
	//n是数字的个数,s是数字字符串
	scanf("%d", &n); 
	cin >> s;
	int sum = 0; //sum用来保存前i个数字的和
	//第一层循环用来枚举前i位数字的和
	for(int i = 0; i < n - 1; i++){
		sum += s[i] - '0';

		bool ok = true; //ok用来保存本题答案
		int pos = i + 1; //pos主要用来记录第一堆之后的每个数字的下标,起指针的作用
		int sum2 = 0; //sum2用来临时保存第二堆及以后每堆的和
		//每一次循环结束都代表新划分出了一堆
		while(pos < n){
			sum2 = s[pos] - '0';
			pos++;
			//该循环是计算每一堆的数字之和
			while(pos < n && sum2+s[pos]-'0' <= sum){
				sum2 += s[pos] - '0';
				pos++;
			}
			if(sum2 != sum) ok = false;
		}

		if(sum2 != sum) ok = false;
		if(ok){
			printf("YES");
			return 0;
		}
	}

	printf("NO");
	return 0;
}

Curiosity Has No Limits

链接地址

题意:现在给出两组数,第一组是a1, a2, a3, ……, an,第二组是b1, b2, b3, ……, bn。令a1 = c1|c2, b1 = c1&c2,问能不能找到这样符合条件的一组数c1, c2, c3, ……, cn, cn+1。

解题思路:

我的错误思路:
起初我的想法是,现在已经得到的是数组c相邻两个数的交运算和并运算的结果,用暴力匹配应该是可以做出来的,但是我自作聪明想用简单一点的方法试一试
想了好久我觉得既然不能从数组c推出数组a、b的正确性,那我应该试试通过数组a判断数组b是否有可能存在,然后我就列出了a的所有取值对应的c的可能数对以及在该取值下b的所有可能
所有取值

首先得到的结论是b的每一个数都不可能大于a,然后首先设置一个限制条件,若b大于a,则不能得到数组c
然后寻找规律,我发现a, b的值正好是c1, c2的值的,再根据第一个条件就可以进一步通过a来筛选b的值(很明显最后问题出来了,我看漏了当a=3的时候取值问题),然后写到最后我就写不下去了……代码也拿出来参考参考吧,对了,样例通过了

//代码实现
#include <iostream>
#include <vector>

using namespace std;

int main(){
	int n, x;
	scanf("%d", &n);
	n--;
	vector<int> a(n);
	vector<int> b(n);
	vector<int> c(n+1);
	for(int i=0; i<n; i++){
		scanf("%d", &x);
		a[i] = x;
	}
	for(int i=0; i<n; i++){
		scanf("%d", &x);
		b[i] = x;
	}
	for(int i=0; i<n; i++){
		if(a[i] < b[i]){
			printf("NO");
			return 0;
		}
	}
	if(a[0]==a[1] || a[0]==b[1]){
		x = a[0];
		a[0] = b[0];
		b[0] = x;
	}
	c[0] = a[0];
	c[1] = b[0];
	for(int i=1; i<n; i++){
		
		if(b[i] == a[i+1]){
			c[i+1] = b[i];
		}else if(b[i] == b[i+1]){
			x = a[i+1];
			a[i+1] = b[i+1];
			b[i+1] = x;
			c[i+1] = b[i];
//		}else if(a[i]==3 && b[i]==0)){
//			if()
//		}
		else{
			printf("NO");
			return 0;
		}
	}
	printf("YES\n");
	for(int i=0; i<n+1; i++){
		printf("%d ", c[i]);
	}
	return 0;
}

最后还是意识到我的歪门邪道还是跟官方题解搭不上边,于是乎我就参考了官方题解……
总之吧,因为数据不大,还是使用了枚举匹配,好像也挺方便的,代码也放下边了

#include<iostream>

using namespace std;

int main(){
	int n,i,j;
	scanf("%d", &n);
	int a[n+1],b[n+1],t[n+100];
	for(i=0;i<n-1;i++) cin>>a[i];
	for(i=0;i<n-1;i++) cin>>b[i];
	for(i=0;i<4;i++){
		t[0]=i;
		for(j=1;j<n;j++){
			t[j]=a[j-1]+b[j-1]-t[j-1];
			if(((t[j]|t[j-1])!=a[j-1])||((t[j]&t[j-1])!=b[j-1])) break;
		}
		if(j==n) break;
	}
	if(i==4){
		printf("NO");
	}else{
		printf("YES\n");
		for(i=0;i<n;i++)cout<<t[i]<<" ";
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值