A - HRZ 的序列
思路:
仔细读一下题:就能发现如果不同的数大于三个,是肯定不能满足上述条件的,所以思路就是不同的数大于三个直接‘NO’,如果不同的数共一个或者两个,必定成立,所以只需判断一下不同的数为三个的情况,对所有数排好序,分别用数组记录三个不同的数,比较这三个数是否满足等差关系即可。
总结:
一定要注意长整型设置,for循环因为没有设置成long long int 导致在test 5就wa掉,不细心导致得分非常少。
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define f(i,a,b) for(long long int i=a;i<b;i++)
long long int a[100000],c[3];
int main()
{
ios::sync_with_stdio(false);
long long int t;
long long int b;
cin >> t;
f(i, 0, t)
{
int n,count=1,k=0;
cin >> n;
f(j, 0, n)
cin >> a[j];
sort(a, a + n);
b = a[0];
f(j, 1, n)
{
if (b != a[j])
{
count++;
b = a[j];
}
}
b = a[0];
c[0] = a[0];
if (count > 3)
{
cout << "NO" << endl;
}
else if (count == 1||count==2)
{
cout << "YES"<< endl;
}
else if (count == 3)
{
f(j, 1, n)
{
if (b != a[j])
{
k++;
c[k] = a[j];
b = a[j];
}
}
if (c[2]+c[0]== c[1]*2)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
}
return 0;
}
B - HRZ 学英语
题意:
思路:
这道题可以利用尺取法,在遍历整个字符串的时候用a数组标记并用,start,end转换成acsII码-A,来表示是否存在这个字母.
首先end 一直从字符串向右遍历,遇到26个字母和?就进行判断是不是顺序 ,然后继续向右遍历,如果遇到访问过的字母则开始处理start ,start向右遍历到与 直到到达end,然后重复上述操作,直到acount=26就行。
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
string s;
int a[30];
long long acount=0, flag;
long long l = 0, r = 0;
int main(){
ios::sync_with_stdio(false);
cin>>s;
int start,end;
while(r!=s.size())
{
if(s[r] == '?')
{
acount++; r++;
}
else
{
int end = s[r++] - 'A';
if(!a[end])
{
a[end] = 1;
acount++;
}
else
{
int start = s[l++]-'A';
while(start!=end)
{
if(s[l-1]!='?')
a[start] = 0;
acount--;
start = s[l++]-'A';
}
}
}
if(acount==26)
{
flag = 1;
break;
}
}
if(!flag)
{
cout<<-1<<endl;
return 0;
}
for(int i=r-26;i<=r-1;i++)
{
if(s[i]=='?'){
for(int j=0;j<=25;j++)
{
if(!a[j]){
a[j] = 1;
cout<<char(j+'A');
break;
}
}
}
else
cout<<s[i];
}
cout<<endl;
return 0;
}
C - 咕咕东的奇妙序列
题意:
思路:
这道题利用前缀和的方法,求出 x 所在块之前的所有块的长度之和,以及x所在块长度。这样我们就可以确定 x 的位置。
要注意每当x位数变化时,公差会发生变化。这时候可以把该序列子序列项数看作多个公差不同的等差数列的集合。(10i到10(i+1)-1的过程中每次都是增加i+1) .给定一个x,我们可以在确定x的位数的同时利用等差数列求取下一个等差数列的首项,同时将不同等差数列项数加起来以确定无限序列的总项数。最后可以利用二分法查找进行优化。
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int q, flag;
long long count2;
long long ans[100];
long long prefix(long long int a, int flag)
{
long long x = 1, y = 1, ans = 0;
for (; 10 * y <= a; x++, y = y * 10)
{
if (flag)
{
ans = ans + x * ((1 + 9 * y) * (9 * y) / 2) + x * (y * 9) * (a - y * 10 + 1);
}
else
{
ans = ans + x * (y * 9);
}
}
if (flag)
{
return ans + x * (a - y + 2) * (a - y + 1) / 2;
}
else return ans + x * (a - y + 1);
}
void count1(long long a)
{
memset(ans, 0, sizeof(ans));
long long tot = 0, b, c;
b = 0, c = 0;
long long start = 0, end = 1e9;
while (start < end - 1)
{
long long mid = (start + end) / 2;
if (prefix(mid, 1) < a)
{
start = mid;
b = mid;
}
else end = mid;
}
a = a - prefix(b, 1);
start = 0;
end = b + 1;
while (start < end - 1)
{
long long mid = (start + end) / 2;
if (prefix(mid, 0) < a)
{
start = mid;
c = mid;
}
else end = mid;
}
a = a - prefix(c++, 0);
while (c)
{
ans[tot++] = c % 10;
c = c / 10;
}
cout << ans[tot - a] << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin >> q;
for (int i = 0; i < q; i++)
{
cin >> count2;
count1(count2);
}
return 0;
}