1. 程式人生 > >#10005. 「一本通 1.1 練習 1」數列極差

#10005. 「一本通 1.1 練習 1」數列極差

【題目描述】

佳佳的老師在黑板上寫了一個由 n個正整陣列成的數列,要求佳佳進行如下操作:每次擦去其中的兩個數 a 和 b,然後在數列中加入一個數 a×b+1,如此下去直至黑板上剩下一個數為止,在所有按這種操作方式最後得到的數中,最大的為 max,最小的為 min⁡, 則該數列的極差定義為 M=max⁡−min⁡。

由於佳佳忙於準備期末考試,現請你幫助他,對於給定的數列,計算出相應的極差 M。

【輸入格式】

第一行為一個正整數 n 表示正整數序列的長度;
在接下來的 n 行中,每行輸入一個正整數。
接下來的一行有一個 0,表示資料結束。

【輸出格式】

輸出只有一行,為相應的極差 M。

【樣例輸入】

3
1
2
3
0

【樣例輸出】

2

【資料範圍與提示】

對於全部資料,0≤n≤50000,保證所有資料計算均在 32位有符號整數範圍內。

思路:看到這道題目真的覺得我在loj做了這麼久的貪心題,看上去最和藹可親的一題了。思路很簡單,定義一個a陣列,為輸入的陣列,然後定義一個b陣列,為複製a陣列的陣列,因為我們要用最大值和最小值來相減,所以我們必然要定義兩個陣列來儲存兩個量。重點就是排序,一個數組從小到大排序,一個數組從大到小排序。因為題目說了,每進行一次,就會減少一個數,所以我們在每一次減少的時候都必須要重新排序。才能使得之後的數都是我們想要的順序,這樣才能方便輸出。大概寫了這麼多之後,歸根到底就是幾個字:
定義陣列->排序->減數->排序->輸出。接下來就看程式碼吧,我會放出三個程式碼:第一個是把後一個數變為要更換的是,第二個是把前一個數變為要更換的數,第三個就是分兩個迴圈分別求出最大值和最小值。

【程式碼一】

/*
	題目解釋,
	求一堆數裡面的兩兩組合消滅之後的最大值和最小值
	輸出最大值與最小值的差值
	然後題目說有一個結束符0,千萬不要被這個結束符給迷惑了
	然後就用了超級複雜的多組資料
	其實就是簡單的輸入n+1個數字,因為題目說了:“
	在接下來的n行中,每行輸入一個正整數。”(真香——) 
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()//日常快讀 
{
	char c=getchar();
	int x=0,f=1;
	while(c<48 || c>57)
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>=48 && c<=57)
	{
		x=x*10+c-48;
		c=getchar();
	}
	return x*f;
}
bool cmpmin(int n1,int n2)
//min是小的意思,所以這個函式就是從小到大排序 
{
	return n1<n2;
}
bool cmpmax(int n1,int n2)
//max是大的意思,所以這個函式就是從大到小排序 
{
	return n1>n2;
}
int a[51000];//原始輸入陣列 
int b[51000];//複製陣列 
int main()
{
	int n; n=read();
	for(int i=1;i<=n+1;i++)
	{
		a[i]=read(); 
		b[i]=a[i];//複製 
	}
	sort(a+1,a+n+1,cmpmin);//a陣列從小到大排序 
	sort(b+1,b+n+1,cmpmax);//b陣列從大到小排序 
	for(int i=1;i<n;i++)
	//因為要求的是i+1所以如果是到n的話,那i+1就是結束符0 
	{
		a[i+1]=a[i]*a[i+1]+1;
		/*
			我把下一個數更新為當前這個數與下一個數的乘積+1
			其實就是題目要求的 
		*/ 
		b[i+1]=b[i]*b[i+1]+1;
		/*
			我把下一個數更新為當前這個數與下一個數的乘積+1
			其實就是題目要求的,
			注意:b陣列求出來的值應該是與a陣列求出來的值不一樣
			因為b陣列是從大到小排序,a陣列是從小到大 
		*/
		sort(a+i+1,a+n+1,cmpmin);
		/*
			這一步就是a陣列在經過改變之後的從小到大的排序
			剛開始就是這裡亂了,
			注意一下:我們的a[i]已經不存在了,因為我們把a[i]和a[i+1]
			合併成為一個了,所以我們這個時候是從a+i+1開始排序
			而不是有a+1開始,所以有的人在除錯的時候可能會亂
			然後我在強調一下
			這個是從小到大排序,也就是說他的最後一個是最大的 
		*/ 
		sort(b+i+1,b+n+1,cmpmax);
		/*
			這一步就是b陣列在經過改變之後的從小到大的排序
			注意一下:我們的b[i]已經不存在了,因為我們把b[i]和b[i+1]
			合併成為一個了,所以我們這個時候是從b+i+1開始排序
			而不是有b+1開始,
			然後我在強調一下
			這個是從大到小排序,也就是說他的最後一個是最小的  
		*/ 
	}
	printf("%d\n",a[n]-b[n]);
	/*
		我相信我上面講了a陣列的最後一個最大
		b陣列的最後一個最小
		所以他們的最大差值就是 a陣列的最後一個-b陣列的最後一個 
	*/
	return 0;
}

【程式碼二】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
	char c=getchar();
	int x=0,f=1;
	while(c<48 || c>57)
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>=48 && c<=57)
	{
		x=x*10+c-48;
		c=getchar();
	}
	return x*f;
}
bool cmpmin(int n1,int n2)
{
	return n1<n2;
}
bool cmpmax(int n1,int n2)
{
	return n1>n2;
}
int a[51000];
int b[51000];
int main()
{
	int n; n=read();
	for(int i=1;i<=n+1;i++)
	{
		a[i]=read();
		b[i]=a[i];
	}
	for(int i=n;i>=2;i--)
	{
		sort(a+1,a+i+1,cmpmin);
		sort(b+1,b+i+1,cmpmax);
		a[i-1]=a[i]*a[i-1]+1;
		b[i-1]=b[i]*b[i-1]+1;
	}
	printf("%d\n",b[1]-a[1]);
	return 0;
}

【程式碼三】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
	char c=getchar();
	int x=0,f=1;
	while(c<48 || c>57)
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>=48 && c<=57)
	{
		x=x*10+c-48;
		c=getchar();
	}
	return x*f;
}
bool cmpmin(int n1,int n2)
{
	return n1<n2;
}
bool cmpmax(int n1,int n2)
{
	return n1>n2;
}
int a[51000];
int b[51000];
int main()
{
	int n; n=read();
	for(int i=1;i<=n+1;i++)
	{
		a[i]=read();
		b[i]=a[i];
	}
	int t=n;
	int ans1,ans2;
	sort(a+1,a+n+1,cmpmax);
	while(t>1)
	{
		int tmp=a[t]*a[t-1]+1;
		t--;
		a[t]=tmp;
		sort(a+1,a+t+1,cmpmax);
	}
	ans1=a[t];
	sort(b+1,b+n+1,cmpmin);
	t=n;
	while(t>1)
	{
		int tmp=b[t]*b[t-1]+1;
		t--;
		b[t]=tmp;
		sort(b+1,b+t+1,cmpmin);
	}
	ans2=b[t];
	printf("%d",ans1-ans2);
	return 0;
}

 個人最喜歡第一個超級好理解(可能因為是自己寫的)