A.問題描述:
相較於咕咕東,瑞神是個起早貪黑的好孩子,今天早上瑞神起得很早,刷B站時看到了一個序列a,他對這個序列產生了濃厚的興趣,他好奇是否存在一個數K,使得一些數加上K,一些數減去K,一些數不變,使得整個序列中所有的數相等,其中對於序列中的每個位置上的數字,至多隻能執行一次加運算或減運算或是對該位置不進行任何操作。
input:
輸入第一行是一個正整數t表示數據組數。 接下來對於每組數據,輸入的第一個正整數n表示序列a的長度,隨後一行有n個整數,表示序列a。
output:
輸出共包含t行,每組數據輸出一行。對於每組數據,如果存在這樣的K,輸出"YES",否則輸出“NO”。 (輸出不包含引號)
樣例輸入
2
5
1 2 3 4 5
5
1 2 3 4 5
樣例輸出
NO
NO
解題思路
只需要記錄序列中的最大值和最小值,然後遍歷一遍序列如果
a[i]!=(maxx+minn)/2輸出NO否則輸出YES
代碼實現
#include<cstdio>
#include<iostream>
using namespace std;
long long a[100010];
int main()
{
int t,n;
cin>>t;
while(t--)
{
bool flag=0;
long long maxx,minn;
maxx=0;
minn=1e15+10;
//cout<<minn<<endl;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]>maxx) maxx=a[i];
if(a[i]<minn) minn=a[i];
}
for(int i=1;i<=n;i++)
{
if(a[i]!=maxx&&a[i]!=minn&&(maxx-a[i]!=a[i]-minn))
{
flag=1;
break;
}
}
if(!flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
B.HRZ學英語
瑞神今年大三了,他在寒假學會了英文的26個字母,所以他很興奮!於是他讓他的朋友TT考考他,TT想 到了一個考瑞神的好問題:給定一個字符串,從裏面尋找連續的26個大寫字母並輸出!但是轉念一想, 這樣太便宜瑞神了,所以他加大了難度:現在給定一個字符串,字符串中包括26個大寫字母和特殊字 符’?’,特殊字符’?'可以代表任何一個大寫字母。現在TT問你是否存在一個位置連續的且由26個大寫字 母組成的子串,在這個子串中每個字母出現且僅出現一次,如果存在,請輸出從左側算起的第一個出現 的符合要求的子串,並且要求,如果有多組解同時符合位置最靠左,則輸出字典序最小的那個解!如果 不存在,輸出-1! 這下HRZ蒙圈了,他剛學會26個字母,這對他來說太難了,所以他來求助你,請你幫 他解決這個問題,報酬是可以幫你打守望先鋒。
說明:字典序 先按照第一個字母,以 A、B、C……Z 的順序排列;如果第一個字母一樣,那麼比較第二 個、第三個乃至後面的字母。如果比到最後兩個單詞不一樣長(比如,SIGH 和 SIGHT),那麼把短者排 在前。例如
AB??EFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABDCEFGHIJKLMNOPQRSTUVWXYZ
上面兩種填法,都可以構成26個字母,但是我們要求字典序最小,只能取前者。
注意,題目要求的是 第一個出現的,字典序最小的!
輸入格式:
輸入只有一行,一個符合題目描述的字符串。
輸出格式:
輸出只有一行,如果存在這樣的子串,請輸出,否則輸出-1
樣例輸入1:
ABC??FGHIJK???OPQR?TUVWXY?
樣例輸出1:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
樣例輸入2:
AABCDEFGHIJKLMNOPQRSTUVW??M
樣例輸出2:
-1
解題思路
使用滑動窗口的方法求解,一個長度爲26的窗口向右滑動,判斷窗口是否滿足條件。判斷是否滿足條件可以開一個數組記錄每個字符出現的次數,以及’?'字符出現的次數。
代碼實現
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int used[26];
int cnt=0,l,r,len;
char s[1010101];
bool pd()
{
int tot=0;
for(int i=0;i<=25;i++)
{
if(used[i]>1) return false;
if(used[i]==0) tot++;
}
if(tot==cnt) return true;
else return false;
}
void couts()
{
for(int i=l;i<=r;i++)
{
if(s[i]=='?')
{
for(int i=0;i<=25;i++)
if(used[i]==0)
{
used[i]++;
cout<<(char)('A'+i);
break;
}
}
else cout<<s[i];
}
cout<<endl;
}
int main()
{
bool flag=0;
memset(used,0,sizeof(used));
cin>>s;
len=strlen(s);
for(int i=0;i<=25;i++)
{
if(s[i]=='?') cnt++;
else used[s[i]-'A']++;
}
l=0,r=25;
while(r<len)
{
if(pd())
{
flag=1;
couts();
break;
}
if(s[l]=='?') cnt--;
else used[s[l]-'A']--;
if(r+1<len&&s[r+1]=='?') cnt++;
else if(r+1<len) used[s[r+1]-'A']++;
l++,r++;
}
if(!flag) cout<<"-1"<<endl;
return 0;
}
C.咕咕東的奇妙序列
咕咕東 正在上可怕的複變函數,但對於穩拿A Plus的 咕咕東 來說,她早已不再聽課,此時她在睡夢中 突然想到了一個奇怪的無限序列:112123123412345 …這個序列由連續正整數組成的若干部分構成,其 中第一部分包含1至1之間的所有數字,第二部分包含1至2之間的所有數字,第三部分包含1至3之間的所 有數字,第i部分總是包含1至i之間的所有數字。所以,這個序列的前56項會是 11212312341234512345612345671234567812345678912345678910,其中第1項是1,第3項是2,第20項是 5,第38項是2,第56項是0。咕咕東 現在想知道第 k 項數字是多少!但是她睡醒之後發現老師講的東西 已經聽不懂了,因此她把這個任務交給了你。
輸入格式:
輸入由多行組成。
第一行一個整數q表示有q組詢問
接下來第i+1行表示第i個輸入 ,表示詢問第i項數字。
輸出格式:
輸出包含q行
第i行輸出對詢問 的輸出結果。
樣例輸入:
5 1 3 20 38 56
樣例輸出:
1 2 5 2 0
解題思路
一個找規律的題,可以分組找規律,對於前九組,他的最大值都是一位數,每一組的位數是公差爲一的等差數列,前九組共有45位數,合爲一個大組。第二大組爲10-99,全部爲二位數,每一組數位爲公差爲二的等差數列,共有9045個數。以此類推分爲多個組,在查找時先與位數比較,查找他在哪一個大組,又因爲每一個小組位數都是單調遞增,可以使用二分查找確定k所在的小組,在小組內再使用二分找到他是第幾個數,最後確定他是第幾個數的第幾位就可。記得要用longlong存數據。
代碼實現
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long a,q;
long long geT(long long x)
{
long long m=1,x=1,d=0,n=0,sum=0;
while(true)
{
m*=10;
d++;
n=m-m/10;
if(x>m-1)
{
sum+=x*n+n*(n-1)*d/2;
x=x+(n-1)*d+d+1;
}
else
{
n=x-m/10+1;
sum+=x*n+n*(n-1)*d/2;
break;
}
}
return sum;
}
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&a);
long long l=0,r=1e9,mid=0,ans,ss;
long long m=1,cnt=0,len=0,n=0,i=1,y=0,sum=0;
while(l<=r)
{
mid=(l+r)/2;
ss=geT(mid);
if(ss<a)
{
ans=mid;
l=mid+1;
}
else
{
r=mid-1;
}
}
a=a-geT(ans);
while(a)
{
m*=10;
n=m-m/10;
len++;
if(a>n*len)
{
sum+=n;
a-=n*len;
}
else
{
sum+=a/len;
y=a%len;
break;
}
}
if(y==0) printf("%lld\n",sum%10);
else
{
sum++;
while(len!=y)
{
len--;
sum/=10;
}
printf("%lld\n",sum%10);
}
}
return 0;
}