第一题
HRZ的序列
给定一个序列a,判断是否存在一个数K,使得一些数加上K,一些数减去K,一些数不变,使得整个序列中所有的数相等。序列长度n<10^4, 数字|ai|<10^15。
Input
第一行为测试数据的组数n
接下来有n组数据,每一组数据第一行为m,表示接下来输入m个数
Output
输出"YES"或者“NO”
Example
- input
2
5
1 2 3 4 5
5
1 2 3 4 5 - output
NO
NO
解题思路
这个题思路比较简单(菜鸡爆零。。。),只要满足下列条件中的一个即可:
1.所有数相同
2.只有两个不同的数
3.只有三个不同的数而且其中两个的和是第三个数的2倍
代码实现
#include<iostream>
using namespace std;
long long num[3],x;
long long flag,cnt,n;
int main()
{
ios::sync_with_stdio(false);
cin >> cnt;
while(cnt--){
cin >> n;
for(long long i=0;i<n;i++){
cin >> x;
long long j=0;
for(;j<flag&&j<3&&num[j]!=x;j++);
if(j>=flag && flag<3) num[flag++]=x;
else if(num[0]!=x&&num[1]!=x&&num[2]!=x) flag++;
}
if(flag==3){
if(num[0]+num[2]==num[1]*2 || num[0]+num[1]==num[2]*2 || num[1]+num[2]==num[0]*2) ;
else flag++;
}
if(flag<=3) cout << "YES" << endl;
else cout << "NO" << endl;
flag=0;
}
return 0;
}
第二题
HRZ学英语
给定一个字符串,其中包括26个大写字母和特殊字符’?’,’?'可以代表任何一个大写字母。现问是否存在一个位置连续的且由26个大写字母组成的子串,在这个子串中每个字母只出现一次。若存在,请输出从左侧算起的第一个出现的符合要求的子串,若有多组解同时符合位置最靠左,则输出字典序最小的那个解。若不存在,输出-1。
Input
一个字符串
Output
相应的字符串或者-1
Example
- input1
ABC??FGHIJK???OPQR?TUVWXY? - output1
ABCDEFGHIJKLMNOPQRSTUVWXYZ - input2
AABCDEFGHIJKLMNOPQRSTUVW??M - output2
-1
解题思路
从第25个字母开始遍历字符串, 开一个长度为26的数组来进行统计来判断数组中的26个字母各不相同,同时通过这个数组来找出 ‘?’ 对应的字母。然后将字符串中 ‘?’ 替换为指定的字母即可。若替换后得到的字符串中各不相同的字母数等于26, 就输出该字符串;找到末尾字符串仍然不符合要求输出-1.
代码实现
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int l, m, cnt,sum,r = 25,index=25;
int flag[26] = {0};
string s,res;
bool judge=0;
int main()
{
ios::sync_with_stdio(false);
res = "00000000000000000000000000";
cin>>s;
while(index<s.size())
{
m = 0;
cnt = l+26;
memset(flag, 0, sizeof(flag));
for(int i=l;i<cnt;i++)
{
if(s[i]!='?')
{
res[i-l] = s[i];
flag[s[i]-'A'] = 1;
}
}
for(int i=l;i<cnt;i++)
{
if(s[i]=='?')
{
for(int j=0;j<26;j++)
if(!flag[j])
{
res[i-l] = j + 'A', flag[j] = 1;
break;
}
}
}
l++;
sum = 0;
for(int i=0;i<26;i++)
if(flag[i]==1)
sum++;
if(sum==26)
{
judge = 1;
break;
}
index++;
}
if(judge) cout << res;
else cout<<-1;
return 0;
}
第三题
咕咕东的奇妙序列
112123123412345 …这个序列由连续正整数组成的若干部分构成,其中第一部分包含1至1之间的所有数字,第二部分包含1至2之间的所有数字,第三部分包含1至3之间的所有数字,第i部分总是包含1至i之间的所有数字,11212312341234512345612345671234567812345678912345678910,其中第1项是1,第3项是2,第20项是5,第38项是2,第56项是0。现在想知道第 k 项数字是多少。
Input
第一行是测试数据的组数n,接下来会有n组测试数据,每组会输入一个数字,要求出序列里对应的数字
Output
输出序列对应数字
Example
- input
5
1
3
20
38
56 - output
1
2
5
2
0
解题思路
这个题乍一看很简单,当发现第56个数字为0的时候觉得不对劲。。。
然后发现每小部分是等差数列:
1 1
12 2
123 3
(差为1)
12345678910
1234567891011
123456789101112
(差为2)
每大部分分别讨论:1-9(10-1)、10-99((10-1)*10)、100-999((10-1)1010)
然后再使用二分搜索数字,找到res,前res部分总位数小于或等于k,求出前res部分总位数,第res+1部分第(k减去前res部分总位数)位就为答案。
代码实现
#include<iostream>
using namespace std;
int q;
long long k;
long long get_index(long long val) {
long long e = 1, s = 1, d = 0, n = 0, index = 0;//start end
while (true) {
n = 9 * e;
e *=10;//每一段的结尾数字
d++;//等差数列的差
if (val < e) {
n = val - e / 10+1;
index += s * n + n * (n - 1)*d / 2;
break;
}
index += s * n + n * (n - 1)*d / 2;//等差数列公式
s += (n - 1)*d + d + 1;
}
return index;
}
int main() {
cin >> q;
while (q--) {
cin >> k;
int l = 0, r = 1e9, mid = 0, index;
while (r>=l) {
mid = (l + r) / 2;
long long res = get_index(mid);
if (res >= k) r = mid - 1;
else
{
index = mid;
l = mid + 1;
}
}
k = k - get_index(index);
long long e = 1, d = 0, n = 0, res = 0,pos=0;
while (k) {
n = 9 * e;
e *= 10;
d++;
if (k <= n*d)
{
res += k / d;
pos = k % d;
break;
}
res += n;
k -= n * d;
}
if (pos == 0) cout << res % 10 << endl;
else {
res++;
for (; d != pos;d--) res /= 10;
cout << res % 10 << endl;
}
}
return 0;
}
赛后总结
这次直接爆零。。。裂开,第一题是细节思考不到位,然后导致re,第二题情况考虑没全面导致wa,第三题。。开始不会做,后来思考后把代码敲了出来
第二题因为用了index与编译器关键字冲突导致ce(我傻了),第三题se(少见的运气)
CSP好难呀
tcl。。。