Week8 CSP-M2

A - HRZ 的序列

在这里插入图片描述在这里插入图片描述

题意:
对于一个序列,有+k,-k,不变三个操作,对所有数字只执行一个操作,如果序列中的数能够边相同则输出“YES”,否则输出“NO”。

分析:
首先对序列进行排序,然后统计序列中出现不同数字的个数,显然当个数大于3时,一定输出“NO”,小于3时一定输出“YES”,等于3时,假设这三个数升序排列为a1、a2、a3,则当2*a2=a1+a3时,输出“YES”,否则输出“NO”。

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;

long long int a[10010];
long long int b[10];

int main()
{
	int t, n;
	cin >> t;
	while (t--)
	{
		cin >> n;
		for (int i = 0; i < n; i++)
			cin >> a[i];
		sort(a, a + n);
		int j = 0;
		b[j] = a[j];
		for (int i = 1; i < n; i++)
		{
			if (a[i] != a[i - 1])
			{
				j++;
				if (j >= 3)
				{
					cout << "NO" << endl;
					break;
				}
				b[j] = a[i];
			}
		}
		if (j <= 1)
			cout << "YES" << endl;
		else if (j == 2)
		{
			int c = b[0] + b[2];
			int d = b[1] * 2;
			if (c == d)
				cout << "YES" << endl;
			else
				cout << "NO" << endl;
		}
	}
	return 0;
}

B - HRZ 学英语

在这里插入图片描述在这里插入图片描述在这里插入图片描述

题意:
在一个字符串中,输出含有26个字母并且字典序最小的序列,若不存在则输出-1,“?”可以代表任意字母。

分析:
首先使用substr()函数截取26个字母,然后记录每个字母(不包含“?”)出现的次数,如果有任何一个字母出现次数大于1,则输出-1,否则,对“?”进行赋值,从A~Z,检查是否出现过,若没有出现过则赋值给“?”,遍历后输出新的字符串。

代码如下:

#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;

int num[26] = { 0 };
bool label;

int main()
{
	string s, ans;
	cin >> s; 
	for (int i = 0; i < s.size() - 25; i++)
	{
		memset(num, 0, sizeof(num));   
		label = false;
		ans = s.substr(i, 26);    
		for (int j = 0; j < 26; j++)
		{ 
			if (ans[j] - 'A' >= 0 && ans[j] - 'A' < 26)
				num[ans[j] - 'A']++;   
			if (num[ans[j] - 'A'] >= 2)
				label = true;
		}
		if (label) 
			continue;
		for (int i = 0; i < 26; i++)
		{
			if (num[i] == 0)
				ans[ans.find('?')] = (char)(i + 'A');
		}
		cout << ans;
		return 0;
	}
	cout << "-1" << endl;
	return 0;
}

C - 咕咕东的奇妙序列

在这里插入图片描述在这里插入图片描述在这里插入图片描述

题意:
有一个特殊规律的序列,输出这个序列的任意一项。

分析:
这道题刚开始思路就不是很清晰,知道是找规律和二分查找,但写了半天没什么结果,就面向数据编程骗了30分,课下写了很多次,但总是被第7个点卡住。
这道题的主要思路为,将序列分为很多大块,每个大块又分为很多小块,在查询某一项时,先利用二分法查找出它属于哪个大块中,再二分法查找出它属于大块中的哪个小块中。最后循环查找需要输出的一项并输出。
这道题的难点是对于数据范围的控制,虽然算法很简单,但数据范围不好选,稍微不注意就会出现很多错误。

代码如下:

#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cmath>
#define ll long long
using namespace std;

const int maxn = 100010;
ll q, n, p1, p2;
ll ans[20];

ll gs(ll x, int flag)
{
	ll i = 1, j = 1, ans = 0;
	for (; 10 * j <= x; i++, j *= 10) 
	{
		if (flag)
			ans += i * ((1 + 9 * j) * 9 * j / 2) + i * j * 9 * (x - j * 10 + 1);
		else
			ans += i * 9 * j;
	}
	return flag ? (ans + i * (x - j + 2) * (x - j + 1) / 2) : (ans + i * (x - j + 1));
}

int main() 
{
	cin >> q;
	while (q--) 
	{
		cin >> n;
		memset(ans, 0, sizeof(ans));
		int tot = 0, p1 = 0, p2 = 0;
		ll l = 0, r = 1e9;
		while (l < r - 1)
		{
			ll mid = (l + r) >> 1;
			if (gs(mid, 1) < n)
			{
				l = mid;
				p1 = mid;
			}
			else
				r = mid;
		}
		n -= gs(p1, 1);
		l = 0, r = p1 + 1;
		while (l < r - 1)
		{
			ll mid = (l + r) >> 1;
			if (gs(mid, 0) < n)
			{
				l = mid;
				p2 = mid;
			}
			else
				r = mid;
		}
		n -= gs(p2++, 0);
		while (p2)
		{
			ans[tot++] = p2 % 10;
			p2 /= 10;
		}
		cout << ans[tot - n] << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值