第三次双周赛

目录

第一道题:打字

 思路:

代码:

第二道题: 分香肠

思路: 

 代码:

第三道题:会议安排

思路:

代码:

第四道题:神秘密码(外星人密码)

 思路:

代码:

第五道题:国王游戏

 思路:

 代码:


第一道题:打字

 

 思路:

这道题主要是理解题目意思,难度不大,是一道签到题。

代码:

#include<bits/stdc++.h>
using namespace std;
int r[9], l[9];
int main() {
	string s; cin >> s;
	for (int i = 0; i < s.size(); i++) {
		if (s[i] == '1' || s[i] == 'Q' || s[i] == 'Z' || s[i] == 'A')r[1]++;
		else if (s[i] == '2' || s[i] == 'W' || s[i] == 'S' || s[i] == 'X')r[2]++;
		else if (s[i] == '3' || s[i] == 'E' || s[i] == 'D' || s[i] == 'C')r[3]++;
		else if (s[i] == 'V' || s[i] == 'F' || s[i] == 'R' || s[i] == '4' || s[i] == 'B' || s[i] == 'G' || s[i] == 'T' || s[i] == '5')r[4]++;
		else if (s[i] == '6' || s[i] == 'Y' || s[i] == 'H' || s[i] == 'N'|| s[i] == '7' || s[i] == 'U' || s[i] == 'J' || s[i] == 'M')l[1]++;
		else if (s[i] == '8' || s[i] == 'I' || s[i] == 'K' || s[i] == ',')l[2]++;
		else if (s[i] == '9' || s[i] == 'O' || s[i] == 'L' || s[i] == '.')l[3]++;
		else if (s[i] == '0' || s[i] == 'P' || s[i] == ';' || s[i] == '/'|| s[i] == '-' || s[i] == '[' || s[i] == '\'' || s[i] == '=' || s[i] == ']')l[4]++;
	}
	for (int i = 1; i <= 4; i++) {
		cout << r[i] << endl;
	}
	for (int i = 1; i <= 4; i++) {
		cout << l[i] << endl;
	}
	return 0;
}

第二道题: 分香肠

思路: 

这道题有点小意思,其实主要是将香肠想成一根,并且提前切了几刀罢了,而假设目前你要分成N段你依旧要均切N-1刀,而假设和之前切的那几刀有重合则再减去重复刀数,就拿4根香肠和6人分来举个例子吧,画了一个丑图讲究看看哈,可以注意到原本要切6-1=5刀可是因为1/2的部分有刀重合则再减去一刀,故答案为4刀,这样分析完之后代码应该没有什么难度了

 代码:

#include<bits/stdc++.h>
using namespace std;
double a[100005];
int main() {
	double N, M; cin >> N >> M;
	for (int i = 1; i <= N - 1; i++) {
		a[i] = i / N;
	}
	int cnt = 0;
	for (int i = 1; i <= M - 1; i++) {
		double x = i / M;
		if (*lower_bound(a + 1, a + (int)N,x)==x)cnt++;
	}
	cout << M-cnt-1 << endl;
	return 0;
}

第三道题:会议安排

 

思路:

这个题是一个很简单的最少失约问题,遵循的原则是能去就去,可是也可以反悔,一开始对起始时间进行排序

首先可以定义一个目前的时间now,当now<下一场的开始的时间的时候,说明可以去,

则根据能去就去的原则,我们肯定要去的,则now=下一场结束的时间,但是呢,如果now>下一场的开始的时间的时候,说明不能去,这时候我们就要比较now和下一场结束时间谁前谁后了,如果now<结束时间,那可以知道这个肯定是不值得的参加,没必要反悔,去参加这一场,但是呢,如果now>下一场结束时间的话,那说明这个虽然是迟一点开场但是走的早,可以有更多的机会参加其他的聚会,则这时候反悔去参加这个聚会

下面举个例子 ,可以结合代码看

代码:

#include<bits/stdc++.h>
using namespace std;
struct num {
	int st;
	int ed;
};
int pop;
num a[10005];
int main() {
	int t; cin >> t;
	for (int i = 0; i < t; i++) {
		int n; cin >> n;
		for (int m = 0; m < n; m++) {
			cin >> a[m].st >> a[m].ed;
		}

		sort(a, a + n, [](num a, num b) {
			return a.st < b.st;
			});
		int pop = 0, now = 0;
		for (int r = 0; r < n; r++) {
			if (now <= a[r].st) {
				pop++;
				now = a[r].ed;

			}
			else {
				if (now > a[r].ed) {
					now = a[r].ed;
				}
			}
		}
		cout <<pop << endl;
	}
	return 0;
}

第四道题:神秘密码(外星人密码)

 思路:

这个是一个很巧妙的递归,详细的解释注解在代码旁边了

代码:

#include<bits/stdc++.h>
using namespace std;
string read()
{
	int cnt;//用来记录循环次数
	string ans = "";
	string temp_s;
	char c;
	while (cin>>c)
	{
		if (c == '[')
		{
			cin >> cnt;//'['后面必定跟数字即为循环次数
			temp_s = read();//递归回去读取循环的字母,且注意返回的是ans
			while (cnt--)
			{
				ans += temp_s;//重复
			}
		}
		else if (c == ']')
		{
			return ans;//注意返回的是重复后的
		}
		else
		{
			ans += c;
		}
	}
}
int main()
{
	cout << read();
	return 0;
}

第五道题:国王游戏

 思路:

比较好理解,我这里复制了证明可以自行参考,主要是贪心算法高精度的结合考察,但是我看了看洛谷上很多AC代码,发现他们都有挨个比较的过程,但是我百思不得其解,根据数学角度,应该是排序后的最后一个会拿到最大值,第一次交了上去果不其然一个测试点没有过,大臣左手全是1的,而右手的金币数量很大,而这时候最大值应该会在第一个上面,而这时候就可以知道了前面的结论并不正确,而正确的结论为为答案是在排完序后第一个和最后一个之间获得金币的最小值

 代码:

#include<bits/stdc++.h>
using namespace std;
struct person
{
	long long r;
	long long l;
};
person a[10050];
int sum[10010],ans[10010];
int lens = 1,lena;
void muti(long long x)
{
	int tmp = 0;
	for (int i = 1; i <= lens; i++)
		sum[i] *= x;
	for (int i = 1; i <= lens; i++)
	{
		tmp += sum[i];
		sum[i] = tmp % 10;
		tmp /= 10;
	}//进位
	while (tmp != 0)
	{
		lens++;
		sum[lens] = tmp % 10;
		tmp /= 10;
	}//最后一位的进位
}
void divi(long long x) {
	memset(ans, 0, sizeof(ans));
	lena = lens;
	int tmp = 0;
	for (int i = lena; i >= 1; i--)
	{
		tmp *= 10;
		tmp += sum[i];
		if (tmp >= x)
		{
			ans[i] = tmp / x;
			tmp %= x;
		}
	}
	while (ans[lena] == 0)
	{
		if (lena == 1)
			break;
		lena--;
	}
}
bool judge(long long x)
{
	string J = to_string(x);
	if (J.size() < lena) {
		return true;
	}
	else if (J.size() == lena)
	{
		int cnt = lena;
		while (true)
		{
			if (cnt == 0)return true;//其实表面俩个相等,返回真或假都可以
			if (ans[cnt] > J[cnt - 1] - '0') return true;
			else if (ans[cnt] == J[cnt - 1] - '0')	cnt--;
			else return false;
		}
	}
	else return false;
}
int main() {
	int n; cin >> n;
	long long R, L; cin >> L >> R;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].l >> a[i].r;
	}
	sort(a + 1, a + 1 + n, [](person a, person b) {return (a.l * a.r < b.l * b.r)||(a.l * a.r == b.l* b.r&&a.r<b.r); });
	sum[1] = L;
	for (int i = 1; i <= n - 1; i++) {
		muti(a[i].l);
	}
	divi(a[n].r);
	if (judge(L / a[1].r)) {
		for (int i = lena; i >= 1; i--) cout << ans[i];
	}
	else cout << L / a[1].r;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值