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;
}