A-HRZ的序列
描述
思路
本题其实非常简单,但考试的时候吧这道题想得太复杂导致出错。
观察题意,让某个数加k,某些数减k,如果只有两个数其实就是平均值的问题,三个数也是要求最大数与最小数的平均值等于中间的数,但数量一多,要求就更多,因为k是固定的,而且发现数的种类一旦大于三,就不可能满足题意,因为每个数只能有三种操作,要让三个不同的数通过这三种操作得到相同的数,肯定是分别采用不同的操作所以数的种类只能小于等于三,所以问题就简单了,先求出数d
实验代码
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int t; cin >> t;
while (t--) {
int n; cin >> n;
long long* a = new long long[n];
int b;
for (int i = 0; i < n; i++) cin >> a[i];
sort(a, a + n);
long long* count = new long long[4];
int c = 0;
for (int i = 0; i < n; i++) {
if (c > 3)break;
else if (c == 0 || a[i] != count[c-1])
count[c++] = a[i];
}
if (c > 3)cout << "NO" << endl;
else if (c == 3) {
if (count[0] + count[2] == 2 * count[1])cout << "YES" << endl;
else cout << "NO" << endl;
}
else if (c == 1 || c == 2)cout << "YES" << endl;
}
return 0;
}
B-HRZ学英语
描述
思路
本题考试的时候属实可惜,我记错了substr函数的参数导致截取长度不对,下来改了一下参数就过了。
本题采用的是类似尺取法,只不过这里的区间长度始终是26,我们先把l与r分别置为0和25,求得区间里面每个字符的个数,如果某个字符的个数大于1,则不满足条件,如果个数为0 的字符数量不等于?的数量,也不满足条件,不满足条件,l和r同时右移,继续相同的操作,找到第一个满足条件的就停止,将?替换为个数为零的字符(小的优先)输出的即可。
实验代码
#include <iostream>
#include <cstring>
using namespace std;
int sum[28];
void add(char op) {
if (op == 'A')sum[1]++;
else if (op == 'B')sum[2]++;
else if (op == 'C')sum[3]++;
else if (op == 'D')sum[4]++;
else if (op == 'E')sum[5]++;
else if (op == 'F')sum[6]++;
else if (op == 'G')sum[7]++;
else if (op == 'H')sum[8]++;
else if (op == 'I')sum[9]++;
else if (op == 'J')sum[10]++;
else if (op == 'K')sum[11]++;
else if (op == 'L')sum[12]++;
else if (op == 'M')sum[13]++;
else if (op == 'N')sum[14]++;
else if (op == 'O')sum[15]++;
else if (op == 'P')sum[16]++;
else if (op == 'Q')sum[17]++;
else if (op == 'R')sum[18]++;
else if (op == 'S')sum[19]++;
else if (op == 'T')sum[20]++;
else if (op == 'U')sum[21]++;
else if (op == 'V')sum[22]++;
else if (op == 'W')sum[23]++;
else if (op == 'X')sum[24]++;
else if (op == 'Y')sum[25]++;
else if (op == 'Z')sum[26]++;
else if (op == '?')sum[27]++;
return;
}
void sub(char op) {
if (op == 'A')sum[1]--;
else if (op == 'B')sum[2]--;
else if (op == 'C')sum[3]--;
else if (op == 'D')sum[4]--;
else if (op == 'E')sum[5]--;
else if (op == 'F')sum[6]--;
else if (op == 'G')sum[7]--;
else if (op == 'H')sum[8]--;
else if (op == 'I')sum[9]--;
else if (op == 'J')sum[10]--;
else if (op == 'K')sum[11]--;
else if (op == 'L')sum[12]--;
else if (op == 'M')sum[13]--;
else if (op == 'N')sum[14]--;
else if (op == 'O')sum[15]--;
else if (op == 'P')sum[16]--;
else if (op == 'Q')sum[17]--;
else if (op == 'R')sum[18]--;
else if (op == 'S')sum[19]--;
else if (op == 'T')sum[20]--;
else if (op == 'U')sum[21]--;
else if (op == 'V')sum[22]--;
else if (op == 'W')sum[23]--;
else if (op == 'X')sum[24]--;
else if (op == 'Y')sum[25]--;
else if (op == 'Z')sum[26]--;
else if (op == '?')sum[27]--;
return;
}
string s; int n;
bool check() {
int count = 0;
for (int i = 1; i <= 26; i++) {
if (sum[i] > 1)return false;
if (sum[i] == 0)count++;
}
if (count == sum[27])return true;
return false;
}
int main() {
cin >> s;
n = s.size();
if (n < 26) {
cout << "-1" << endl;
return 0;
}
int l = 0, r = 25;
memset(sum, 0, sizeof(sum));
for (int i = l; i <= r; i++)
add(s[i]);
string ans = "0";
while (r <= n - 1) {
if (check() == true) {
ans = s.substr(l, 26);
break;
}
sub(s[l]); l++; r++;
add(s[r]);
}
if (ans == "0")cout << "-1" << endl;
else {
int temp = 0;
for (int i = 1; i <= 26; i++) {
if (sum[i] == 0) {
for (int j = temp; j < 26; j++) {
if (ans[j] == '?') {
ans[j] = 'A' + i - 1;
break;
}
}
}
}
cout << ans << endl;
}
return 0;
}
C-咕咕东的奇妙序列
描述
思路
本题做完发现两位数占两位,三位数占三位。。。来不及更改代码了。
本题的思路是先求出每位数的最大序列长度,每位数中的最小数所占用的序列长度,然后判断所给的k值在哪个范围,知道位数之后就好办了,但由于数值过大,迭代寻找肯定会超时,所以我们先确定了位数之后,采用二分查找求出小于等于k值的最大mid,最后k减去这个mid对应的序列长度,对剩下的序列单独做就好做了,对剩下的序列同样可以采用二分法,这里我没有使用,而是采用数学方法找出剩余序列所能到达的位数,减去该位数的最小数所占用的序列长度,再对剩下做处理就很简单了。
本题有许多细节的地方需要仔细考虑,在做的过程中也出现了许多考虑不周的问题,但是后面因为编译器选择错误导致卡了很长一段时间,换了编译器就对了。
实验代码
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;
static long long a[15];
static long long b[15];
int main() {
long long sum = 56;
a[0] = 0; b[0] = 0;
a[1] = sum; b[1] = 1;
long long a1 = 1;
long long an = 10;
long long n = 0;
for (int m = 2; m <=10 ;m++) {
a1 = an + 1 + m;
n = pow(10, m) - pow(10, m-1);
an = a1 + (n-1) * m;
sum += (a1 + an) * n / 2 + 1;
a[m] = sum; b[m] = a1;
}
//for (int i = 0; i <= 10; i++)cout << a[i]<< " "<<b[i] << endl;
int q; cin >> q;
while (q--) {
long long k ;
scanf("%lld", &k);
long long i;
for (i = 0; i < 10; i++)
if (a[i] > k)break;
long long l, r;
if (i == 1) {
l = 1; r = 10;
}
else {
l = pow(10, i - 1)+1;
r = pow(10, i);
}
long long ans1 = a[i - 1], ans2 = pow(10, i - 1);
long long temp = l;
while (l <= r) {
long long mid = l + r >> 1;
a1 = b[i]; an = a1 + (mid - temp) * i;
sum = (a1 + an) * (mid - temp + 1) / 2 + a[i - 1];
if (mid == pow(10, i))sum++;
//cout << l << " " << mid << " " << r << " " << sum << endl;
if (sum > k)r = mid - 1;
else if (sum <= k) {
l = mid + 1;
ans1 = sum;
ans2 = mid;
}
}
//cout << ans1 << " " << ans2 << endl;
k -= ans1;
if (k == 0)cout << ans2 % 10 << endl;
else {
long long j;
for (j = 2; j <= 10; j++)
if (k < b[j] - j)break;
//cout << k << " " << j << " " << b[j] << endl;
if (k > b[j] - j-j) {
k -= (b[j] - j - j);
if (k == 1)cout << "1" << endl;
else cout << "0" << endl;
}
else {
if (j != 2)
k -= (b[j - 1] - j - j + 2);
long long d = j - 1;
long long ans = k / d;
k -= ans * d;
ans += (pow(10, j - 2) - 1);
if (k != 0) {
ans++;
for (int m = k; m < j - 1; m++)ans /= 10;
}
cout <<ans % 10 << endl;
}
}
}
return 0;
}