程序设计CSP模拟测试【Week8】

A题

题意:
相较于咕咕东,瑞神是个起早贪黑的好孩子,今天早上瑞神起得很早,刷B站时看到了一个序列 ,他对
这个序列产生了浓厚的兴趣,他好奇是否存在一个数 ,使得一些数加上 ,一些数减去 ,一些数不
变,使得整个序列中所有的数相等,其中对于序列中的每个位置上的数字,至多只能执行一次加运算或
减运算或是对该位置不进行任何操作。由于瑞神只会刷B站,所以他把这个问题交给了你!

输入格式

输入第一行是一个正整数 表示数据组数。 接下来对于每组数据,输入的第一个正整数 表示序列 的长
度,随后一行有 个整数,表示序列a 。
输出格式

输出共包含 行,每组数据输出一行。对于每组数据,如果存在这样的K,输出"YES",否则输出“NO”。(输出不包含引号)

输入样例
2
5
1 2 3 4 5
5
1 2 3 4 5

输出样例

NO
NO

思路:
1.模测的时候,递交了也不知道思路对不对。输出的时候与输出样例也相同就递交了,结果结束的时候没有一个测试点过(哭),原来的思路是算出这个数组的平均值,然后数组的每个元素与平均值作差之间作比较,把数值等于平均值的数字排除,如果比较下来发现相同即可。结果不对(微笑脸)
2.后来去看别人的思路发现:输出YES有两种情况:1.全组有一种数字或者两种数字2.全组有三种数字且作差相等即可
(哎,心里悲伤那么大)

代码:

#include 
#include
#include
#include
#include
using namespace std;
int t, n, di;
long long  a[10010];
long long temp, zl, mid, ri;

int main(void)
{
	cin >> t;
	while (t--)
	{
		di = 1;
		memset(a, 0, sizeof(a));
		//memset(av,0,sizeof(av));
		cin >> n;
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];
		}
		sort(a, a + n);
		temp = a[0], zl = a[0], mid = a[n - 1], ri = a[n - 1];
		if (a[0] == a[n - 1])
		{
			cout << "YES" << endl;
			continue;
		}
		for (int i = 1; i < n; i++)
		{
			if (a[i] != temp)
			{
				if (di == 1)
				{
					mid = a[i];
				}
				else if (di == 2)
				{
					ri = a[i];
				}
				di++;
				temp = a[i];
			}
		}
		if (di == 2)//只有两种值 
		{
			cout << "YES" << endl;
			continue;
		}
		else if (di == 3 && (ri - mid) == (mid - zl))//只有三个数不一样且差值相同 
		{
			cout << "YES" << endl;
			continue;
		}
		else
			cout << "NO" << endl;
	}
	return 0;
}


B题

题意:

给定一个只含26个大写英文字母和’?'的字符串,找出一个连续的且由26个大写字母组成的串,在这个子串中每个字母都只出现一次 '?'可以当做任何字母
如果有,输出最靠左且字典序最小的子串
如果没有 输出"-1"

Input

一个字符串(len<=106)

Output

子串或"-1"

Sample Input 1

ABC??FGHIJK???OPQR?TUVWXY?

Sample Output 1

ABCDEFGHIJKLMNOPQRSTUVWXYZ

Sample Input 2

AABCDEFGHIJKLMNOPQRSTUVW??M

Sample Output 2

-1

思路:
本题的思路类似于滑动窗口,首先判断字符串s的前26个字母,character数组是用来储存字符串中每个元素分别有多少个,例如s[1]=A,对应于character[1]=个数++若s[i]=’?'则cnt++;然后判断character数组中有多少个等于0,que++.
最后判断cnt与que,如果相等则可以用问号代替缺少的元素,如果不相等的话,将右下标右移判断cnt,que同时最左下标往右移判断cnt,que。如果碰到‘\0’则输出-1.

代码:

#include
#include
#include
#include
#include 
using namespace std;

char s[1000010];
int character[27];
int que = 0;
int index1 = 0;
char eng[] = { 0,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
int cnt = 0;

int main()
{
	cin >> s;
	for (int i = 0; i < 27; i++)
		character[i] = 0;
	//cout<<";;;;";
	for (int i = 0; i < 26; i++)
	{
		if (s[i] == '?') cnt++;
		else
		{
			int j = s[i] - 'A' + 1;
			character[j]++;
		}
	}
	//cout<<"...."<
	for (int i = 1; i < 27; i++)
	{
		if (character[i] == 0) que++;
	}
	//cout<
	index1 = 25;
	//char ans[27];
	while (1) {

		if (que == cnt)//问号的个数等于0的个数
		{
			char ans[27];
			for (int i = 1; i <= 26; i++)
				ans[i] = s[index1 - 26 + i];
			int indexb = 0;
			char bu[26];
			for (int i = 1; i <= 26; i++)
			{
				if (character[i] == 0)
				{
					bu[indexb] = eng[i];
					indexb++;
				}
			}
			indexb = 0;
			for (int i = 1; i <= 26; i++)
			{
				if (ans[i] == '?')
					ans[i] = bu[indexb++];
			}

			for (int i = 1; i <= 26; i++)
				cout << ans[i];
			cout << endl;
			break;
		}

		if (s[index1 + 1] == '\0')
		{
			cout << "-1" << endl;
			break;
		}

		index1++;
		if (s[index1] == '?') cnt++;
		else
		{
			int j = s[index1] - 'A' + 1;
			character[j]++;
			if (character[j] == 1) que--;
		}
		if (s[index1 - 26] == '?') cnt--;
		else
		{
			int j = s[index1 - 26] - 'A' + 1;
			character[j]--;
			if (character[j] == 0) que++;
		}


	}
	return 0;
}
#include
#include
#include
#include
#include 
using namespace std;

char s[1000010];
int character[27];
int que = 0;
int index1 = 0;
char eng[] = { 0,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
int cnt = 0;

int main()
{
	cin >> s;
	for (int i = 0; i < 27; i++)
		character[i] = 0;
	//cout<<";;;;";
	for (int i = 0; i < 26; i++)
	{
		if (s[i] == '?') cnt++;
		else
		{
			int j = s[i] - 'A' + 1;
			character[j]++;
		}
	}
	//cout<<"...."<
	for (int i = 1; i < 27; i++)
	{
		if (character[i] == 0) que++;
	}
	//cout<
	index1 = 25;
	//char ans[27];
	while (1) {

		if (que == cnt)//问号的个数等于0的个数
		{
			char ans[27];
			for (int i = 1; i <= 26; i++)
				ans[i] = s[index1 - 26 + i];
			int indexb = 0;
			char bu[26];
			for (int i = 1; i <= 26; i++)
			{
				if (character[i] == 0)
				{
					bu[indexb] = eng[i];
					indexb++;
				}
			}
			indexb = 0;
			for (int i = 1; i <= 26; i++)
			{
				if (ans[i] == '?')
					ans[i] = bu[indexb++];
			}

			for (int i = 1; i <= 26; i++)
				cout << ans[i];
			cout << endl;
			break;
		}

		if (s[index1 + 1] == '\0')
		{
			cout << "-1" << endl;
			break;
		}

		index1++;
		if (s[index1] == '?') cnt++;
		else
		{
			int j = s[index1] - 'A' + 1;
			character[j]++;
			if (character[j] == 1) que--;
		}
		if (s[index1 - 26] == '?') cnt--;
		else
		{
			int j = s[index1 - 26] - 'A' + 1;
			character[j]--;
			if (character[j] == 0) que++;
		}


	}
	return 0;
}

C题

题意:
有一个序列11212312341234512345612345671234567812345678912345678910······
特点为由若干部分组成 每一部分si为1~i所有数字
给出q(q<=500)次查询 每次查询给出一个数字ki(ki<=1018) 请给出序列中第ki个数字
例如 第1项是1,第3项是2,第20项是 5,第38项是2,第56项是0

Input

第一行给出q
接下来2~q+1行 每行一个数字ki

Output

输出包含q行
第i行输出对询问 的输出结果。

Sample Input

5
1
3
20
38
56

Sample Output

1
2
5
2
0

思路:
当初看到这道题的时候只考虑了1—9的情况:算出前n个序列的数字个数,如果大于数字k,则K在第n个序列中,然后再算前x个数的个数,确定K在这个序列中的位置。这个思路我只考虑了1—9的数,当数字是1—10时候,序列个数变为:11、13,15,其实原来到这里就卡了。
之后去看别人写的思路发现,确定k在哪一个部分以及在哪个部分的哪个位置可以用等差数列求前N项和。然后这个查询过程中也可以用到二分查找,查找离K最近的位置。然后K减。思路差不多是这个样子。(真的太厉害了,想到了二分,我完全想不到)

代码:

#include
#include
#include
#include
#include 
using namespace std;

long long k, l, r, mid, ans;
int p;

long long have(long long a, int pos)
{
	long long wr = 1, ss = 0, s = 0, n = 0, d = 0;//ssum算总长度,sum算在i部分的位置
	while (true)
	{
		wr *= 10;
		d++;//公差
		if (a > wr - 1)
		{
			n = wr - wr / 10;
			ss += (s + d) * n + n * (n - 1) / 2 * d;
			s += n * d;
		}
		else
		{
			n = a - wr / 10 + 1;
			ss += (s + d) * n + n * (n - 1) / 2 * d;
			s += n * d;
			break;
		}
	}
	return pos == 1 ? ss : s;
}

int main()
{
	cin >> p;
	for (int i = 0; i < p; i++)
	{
		cin >> k;
		l = 0;
		r = 1e9;
		while (l <= r)
		{//在ss中找到与k最相近的数 
			mid = (l + r) / 2;
			if (have(mid, 1) < k)
			{
				ans = mid;
				l = mid + 1;
			}
			else r = mid - 1;
		}
		k -= have(ans, 1);//在第i部分中的位置
		//cout<
		l = 0;
		r = ans + 1;
		while (l <= r)
		{
			mid = (l + r) / 2;
			if (have(mid, 2) < k)
			{
				ans = mid;
				l = mid + 1;
			}
			else  r = mid - 1;
		}
		//cout<<"???"<
		k -= have(ans, 2);
		ans++;
		string oo = to_string(ans);
		printf("%d\n", oo[k - 1] - '0');
	}
	return 0;
}

你可能感兴趣的:(模拟题)