题一:HRZ的序列
题意:
给出一串序列,求有没有一个数K,使得,序列中的一些数加上K,一些数减去K,一些数不变,使得整个序列所有数相等。
输入格式:
输入第一行是一个正整数 t 表示数据组数。 接下来对于每组数据,输入的第一个正整数 n 表示序列 a 的长 度,随后一行有 n 个整数,表示序列 a。
输出格式:
输出共包含 i 行,每组数据输出一行,如果存在这样的 K,输出“YES”,否则输出“NO”。(输出不包含引号)
思路:
若输入的序列中,所有数相等,必然输出YES;
若输入序列中只有两种数,必然输出YES;
若输入序列中有三种数,若max - mid == mid - min,则输出YES,反之则输出NO;
若输入序列中有超过三种数,则必然输出NO。
为了记录共有多少种数,用一个变量sum来判断;再定义一个变量数组b[3],用来记录三种数的值;再定义一个布尔型数组got[3],用来判断是否已经得到了第 i 种数。
主函数中,在输入完成后,先对序列进行排序。然后依次从第一个数开始判断:若a[i] = b[sum-1],直接判断下一个数,若 a[i] != b[sum-1]:若sum=3,即数据总数超过三种,直接退出循环输出NO;反之,将 a[i] 赋值给 b[sum],sum自加。
在遍历完序列之后,判断如果 b[2] - b[1] = b[1] - b[0] 或者got[2] = false,输出YES,反之输出NO。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
long long a[10005];
int sum = 0;
long long b[3];
bool got[3] = { 0, 0, 0 };
int main()
{
int t, n;
cin >> t;
for (int i = 0; i < t; i++) {
bool can = 1;
got[0] = got[1] = got[2] = 0;
sum = 0;
cin >> n;
for (int j = 0; j < n; j++) {
cin >> a[j];
}
sort(a, a + n);
//cout << a[0] << " " << a[1] << " " << a[2];
int j = 0;
b[0] = a[0];
sum = 1;
j++;
while(j < n) {
//1.前面放进去的和我现在要放的一样
//if (b[sum] == a[j]) {
//啥也别干
//}
// 2.前面放进去的和我现在要放的不一样
if (b[sum - 1] != a[j]) {
//满了
if (sum == 3) {
can = 0;
break;
}
//没满
else {
b[sum] = a[j];
sum++;
}
}
j++;
}
//cout << b[0] << " " << b[1] << " " << b[2];
if (can == 0 || (b[2] - b[1] != b[1] - b[0]) && sum == 3) {
cout << "NO" << endl;
}
else {
cout << "YES" << endl;
}
}
}
题二:HRZ学英语
题意:
给出一个字符串,包含大写字母以及字符 ‘?’。
要求:从该字符串中,取出26位子串,使得该26位子串中包含26位字母,若有‘?’,可以代替任何字母,并且在更换了‘?’之后输出26位字符串,问号部分按字典序代替字母。
输入格式:
输入一行,一个符合题目描述的字符串
输出格式:
输出一行,如果存在这样的子串,输出该子串,否则输出-1。
样例输入1:
ABC??FGHIJK???OPQR?TUVWXY?
样例输出1:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
样例输入2:
AABCDEFGHIJKLMNOPQRSTUVW??M
样例输出2:
-1
思路:
一个char型数组存储字符串,一个int型数组vis用来表示子串中是否已经含有某个字母,一个char型队列queue用来存放子串。
每次从字符串中取出一个字符,判断 vis[str[i]-‘A’] 是否为 0,若为 0,则把该字符放入队列中并把 vis 赋1,若为1,则从队列头开始删除,直到删掉queue.front() = str[i]。
若队列的 size 小于26,输出 -1,反之,开始输出字符串:从queue中取出一个字符,若为‘?’,从vis[0]开始判断直到找到 vis[i] = 0 的位置,输出 (char)(i+‘A’),并把 vis 置1;若不为‘?’,输出字符。
代码:
#include <iostream>
#include <queue>
#include <string>
using namespace std;
char str[1000005];
int vis[26];//vis[0]=vis[A] vis[str[i]-'A']
queue<char> q;
int main()
{
while (q.size()) q.pop();
for (int i = 0; i < 26; i++) vis[i] = 0;
cin >> str;
int i = 0;
while (str[i] != '\0' && q.size() < 26) {
q.push(str[i]);
if (str[i] == '?') {
i++;
continue;
}
if (vis[str[i] - 'A'] == 1) {
while (q.front() != str[i]) {
vis[q.front() - 'A'] = 0;
q.pop();
}
q.pop();
}
vis[str[i] - 'A'] = 1;
i++;
}
if (q.size() < 26) {
cout << "-1" << endl;
return 0;
}
while (q.size()) {
if (q.front() == '?') {
int i = 0;
while (i < 26) {
if (vis[i] == 0) {
cout << (char)(i + 'A');
vis[i] = 1;
break;
}
i++;
}
}
else {
cout << q.front();
//vis[q.front() - 'A'] = 1;
}
q.pop();
}
}
题三:咕咕东的奇妙序列
题意:
有一个序列,第一部分包含1到1之间的数字,第二部分包含1到2之间的数字,第三部分包含1到3之间的数字,…,第i部分包含1到i之间的数字。这个序列前56项是11212312341234512345612345671234567812345678912345678910。
求:第i项数字是多少。
输入格式:
第一行一个整数 q 表示询问 q 次
接下来第 i + 1行表示第 i 个输入
k
i
k_i
ki,表示询问第
k
i
k_i
ki项数字
输出格式:
输出 q 行,第 i 行输出询问
k
i
k_i
ki 的输出结果。
样例输入:
5
1
3
20
38
56
样例输出:
1
2
5
2
0
思路:
首先定义两个数组 a 和 sum,a[i]表示第 i 部分包含几个数字,sum[i] 表示前 i 部分一共包含几个数字。可以通过a[i] = a[i-1]+wei(i),sum[i] = a[i] + sum[i-1],其中wei(i)表示一个数的位数。
给出查询的
k
i
k_i
ki 之后,先在sum数组中找到相应的位置,判断出
k
i
k_i
ki 在第几部分,再在第 i 部分找第 j 位数字,找第 j 位数字时,首先在a数组中找到相应的位置,判断出 j 在第几个数字,再在第 t 个数字中找第 j - a[t-1] 位,即可得到答案。
代码:
#include <iostream>
#include <math.h>
using namespace std;
long long a[2900000];//a[i]表示第i项共有a[i]位
long long sum[2900000];//sum[i]表示前i项共有sum[i]位
//得到x有几位
int wei(int x) {
int w = 0;
while (x != 0) {
x = x / 10;
w++;
}
return w;
}
void init() {
a[0] = 0;
sum[0] = 0;
for (int i = 1; i < 2900000; i++) {
a[i] = a[i - 1] + wei(i);
sum[i] = a[i] + sum[i - 1];
}
}
//在x中找到第y位
int getP(int x, int y) {
int w = wei(x);
x = x / pow(10, w - y);
x = x % 10;
return x;
}
//找到第 i 部分 第 j 位
int getNum(int i, long long j) {//i-10 j-10
//找到 j 在数组 a[] 中的位置
int k = 1;
while (j > a[k]) {
k++;
}
return getP(k, j - a[k - 1]);
}
int main() {
init();
int q;
long long k;
cin >> q;
for (int i = 0; i < q; i++) {
//k = i + 1;
cin >> k;
if (k == 1) {
cout << "1" << endl;
}
else {
int l = 1, r = 2900000, mid;
while (r - l > 1) {
mid = (l + r) / 2;
if (sum[mid] > k) {
r = mid;
}
if (sum[mid] < k) {
l = mid;
}
if (sum[mid] == k) {
r = mid;
break;
}
}
cout << getNum(r, k - sum[r - 1]) << endl;
}
}
}