程序設計思維與實踐CSP第二次模擬題

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章