CSDN竞赛19期题解

总结

本来这次竞赛只是观望下,后面发现奖品还行,高分的也不多,就顺带参加了下。CSDN的竞赛近几期有种卡bug的感觉,能拿名次的不一定算法多强,但是一定是会卡bug的。

题目列表

1.幼稚班作业

题目描述

幼稚园终于又有新的作业了。
老师安排同学用发给同学的4根木棒拼接成一个三角形。
当然按照正常的逻辑,如果不能拼接成三角形。
必然要折断某个木棍来拼接三角形。
可是懒惰的小艺当然不会费力了!
如果拼接不成三角形小艺就会把它凭借成类似边长 1 1 2的伪三角形。
如果伪三角形都拼接不成那就不交作业!

输入描述:

输入四根木棍的长度。

输出描述:

拼接成正常三角形输出”1”,伪三角形输出”0”,否则输出”-1”。

输入样例:

1 2 3 4

输出样例:

1

分析

这次竞赛的第一坑就是这题,从题目描述看,我们是看不出来题意是让我们在四根木棒里选三根拼接成三角形的。正常的理解就是四根中的两根拼成一边,但是从测试用例来看的确是让我们使用三根木棒的。

我们将四根木棒按照长度排成abcd的顺序,然后分别尝试abc和bcd能不能拼成三角形即可。

代码

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
int solution(std::vector<int>& vec) {
	sort(vec.begin(), vec.end());
	if (vec[0] + vec[1] > vec[2] || vec[1] + vec[2] > vec[3]) return 1;
	else if(vec[0] + vec[1] == vec[2] || vec[1] + vec[2] == vec[3]) return 0;
	else return -1;
}
int main() {
	std::vector<int> vec;
	std::string line_0, token_0;
	getline(std::cin >> std::ws,line_0);
	std::stringstream tokens_0(line_0);
	while(std::getline(tokens_0, token_0, ' ')) {
		vec.push_back(std::stoi(token_0));
	}
	int result = solution(vec);
	std::cout<<result<<std::endl;
	return 0;
}

2.环形单向链表

题目描述

给一个单向链表,若其中包含环,请完善EntryNodeOfLoop方法找出该链表的环的入口结点,否则,输出null。要求空间 复杂度为O(1)

分析

这题应该是不少人失分的题目,题目本身出的不太好,也没必要深究。单向链表可能存在环,还可能不止一个环,这就意味着题目给定的数据结构不足以存储这个链表,因为next指针不唯一。题目最终的输入是逐对给出的,合理一点的操作是先转成链表存储,然后遍历链表去找到环的入口,但是由于next可能不唯一,我们存储不方便,甚至没法确定第一个输入是不是头节点。

既然太多未知的输入,我们不妨就以ac为目标。假设题目是从前往后给出链表的节点的,如果给定的输入a b表示a到b有一条数据通路,那么不妨用hash数组记下所有的a,如果读入的b在之前记录的a中出现过,就将a认为是环的入口。这种做法能通过九成的用例。还有一个用例我怀疑是自环,因此可以再加上入度不小于2的判断,就可以ac本题了。

如果仅使用节点的入度超过1来判断环,很可能环的入口就是起点,此时入口的入度等于1,因此这种做法通过不了多少用例,但是入度不小于2尽管不是环的必要条件,却是充分条件,可以帮助我们通过一些特殊的用例。

代码

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <set>
using namespace std;
set<int> s;
bool m[105];
int cnt[105] = {0};
int main() {
	int n;
	std::cin>>n;
	int a, b;
	for (int i = 0; i < n; i++) {
		cin>>a>>b;
		m[a] = true;
		cnt[b]++;
		if (m[b] || cnt[b] >= 2) s.insert(b);
	}
	if (s.size()) {
		for(auto x : s) cout<<x<<endl;
	} else {
		cout<<"null"<<endl;
	}
	return 0;
}

3.影分身

题目描述

已知字符串str。字符串str包含字符’x’,’y’。
如果相邻的两个字符不同,消除两个字符,优先从左边进行消除。
xyyx - > yx ->

输入描述:

输入多个字符。(1<=len<=1e5)

输出描述:

输出最后的分身

输入样例:

xyyyy

输出样例:

yyy

分析

比较简单的模拟题,可以使用栈来模拟,当前字符与栈顶元素不同,则栈顶元素出栈,否则入栈。

代码

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
stack<char> s;
int main() {
	std::string str;
	getline(std::cin, str);
	int n = str.size();
	for (int i = 0; i < n; i++) {
		if (s.size() && str[i] != s.top()) {
			s.pop();
		} else s.push(str[i]);
	}
	string res;
	while(s.size()) {
		res += s.top();
		s.pop();
	}
	reverse(res.begin(), res.end());
	cout<<res<<endl;
	return 0;
}

4.醉酒的狱卒

题目描述

某监狱有一个由n个牢房组成的大厅,每个牢房紧挨着。每个牢房里都有一个囚犯,每个牢房都是锁着的。

一天晚上,狱卒感到无聊,决定玩一个游戏。在第一轮,他喝了一杯威士忌,然后跑下大厅,打开每个牢房的锁。在第二轮比赛中,他喝了一杯威士忌,然后跑下大厅,锁上每隔一个的牢房的锁(牢房2、4、6…)。在第三轮比赛中,他喝了一杯威士忌,然后跑下大厅。他每隔三个牢房(第3、6、9号牢房)就去一次。如果牢房被锁上了,他就把它打开;如果牢房门打开了,他就锁上牢房。他重复n轮,喝最后一杯,然后昏倒。
一些囚犯(可能为零号)意识到他们的牢房被解锁且狱卒丧失了行动能力。他们就可以立即逃跑。现在根据牢房数量,确定有多少囚犯越狱。

输入描述:

第一行输入包含一个正整数t。表示有t行数据,下面每一行都包含一个介于5和100之间(含5和100)的整数,即轮数n

输出描述:

对于每一行,必须打印出监狱有n个牢房时越狱的囚犯人数

输入样例:

2
5
100

输出样例:

2
10

分析

n个牢房,每个数的倍数都会被光顾,因此,只要一个牢房的编号有奇数个因子,那么囚犯就可以逃走。可以直接模拟实现。

当然,如果 a a a n n n的因子,那么 n / a n / a n/a必然也是 n n n的因子,如果 a   ! = n / a a\ != n/a a !=n/a,那么 n n n就多了两个因子,否则多了一个因子。因此只要n是完全平方数,那么这个牢房最后是打开的。问题就转化成了 n n n以内完全平方数的个数,结果是 n \sqrt{n} n 个。

代码

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
int main() {
	int t;
	std::vector<std::vector<std::string>> vec;
	std::cin>>t;
	while(t--) {
		int n;
		cin>>n;
		int res = 0;
		for (int i = 1; i <= n; i++) {
			int cnt = 0;
			for(int j = 1; j <= i; j++) {
				if (i % j == 0) cnt++;
			}
			if (cnt & 1) res++;
		}
		cout<<res<<endl;
	}
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值