[NOIP模擬賽]等差數列

題目描述
麥克在第一張紙上寫下了N個十進制實數。然後,對於每個實數,他都寫下了一個從0開始,以該數爲公差的等差數列。比如當前數爲x,則他寫的等差數列爲0,x,2x,3x,……接下來,他把第一張紙上的所有在區間[A,B]中的數挑選出來,剔除掉重複的,按升序寫在第二張紙上。但第二天,他把第一張紙弄丟了。現在,他請你根據第二張紙還原出第一張紙上的內容。


輸入

第一行包含一個自然數K,(K<=50),表示在第二張紙上有K個數。這些數都是在區間[A,B]之間的。第二行兩個整數A和B(1<=A<B<=106)接下來K行,每行一個實數,按升序排列。每個數最多5位小數。


輸出

N行,每行一個數。表示第一張紙上最開始的N個數。按升序排列。如果有多種可能,則輸出個數最少的一種,如果還有多種,任意輸出一種即可。


樣例輸入

4
1 2
1
1.4
1.5
2


樣例輸出

0.5

0.7


題解:

因爲最多5位小數,就可以先把每個數乘上100000,輸出答案的時候再除回來,方便計算。

首先尋找所有可能合法的差值。然後逐個枚舉,看在當前差值下是否可以組成合法數列。

最後檢驗每個差值是否多餘,刪去多餘的差值。

詳見代碼。


#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
const int N=55;
const int M=1500;

int n;
LL A, B, num[N];

void Getin( LL &shu ) {
	char c; int f=5; shu=0;
	for( c=getchar(); c<'0' || c>'9'; c=getchar() );
	for( ; c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0';
	if( c=='.' ) for( c=getchar(); c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0', f--;
	while( f-- ) shu*=10;
}

map< LL, int >id;
LL d[M], dcnt, ans[N], acnt;
int way[N], cnt[N];

void Find_way( LL d ) {
	LL l=A, wcnt=0;
	if( A%d ) l=(A/d+1)*d;
	for( LL v=l; v<=B; v+=d )//尋找可能的數列
		if( !id[v] ) return;//數列不合法
		else way[++wcnt]=id[v];
	
	bool flg=0;
	for( int i=1; i<=wcnt; i++ )//只要該數列的一個數未在之前的數列中出現過, 該數列有存在的意義
		if( !cnt[ way[i] ] ) { flg=1; break; }
	if( !flg ) return;
	
	ans[++acnt]=d;
	for( int i=1; i<=wcnt; i++ ) cnt[ way[i] ]++;
}

void Judge( int i, LL d ) {
	LL l=A;
	if( A%d ) l=(A/d+1)*d;
	
	bool flg=0;
	for( LL v=l; v<=B; v+=d )//若該數列的所有數都在之前出現過不止一次, 該數列沒有存在的意義
		if( cnt[ id[v] ]==1 ) { flg=1; break; }
	if( !flg ) ans[i]=0;
}

int main() {
	scanf( "%d", &n );
	Getin(A); Getin(B);
	
	for( int i=1; i<=n; i++ ) {
		Getin( num[i] ); id[ num[i] ]=i;
		for( int j=0; j<i; j++ )
			d[++dcnt]=num[i]-num[j];//找可能的差值
	}
	sort( d+1, d+dcnt+1 );
	dcnt=unique( d+1, d+dcnt+1 )-d-1;
	
	for( int i=1; i<=dcnt; i++ ) {
		bool flg=0;
		for( int j=1; j<=acnt; j++ )//該差值是之前某一合法差值的的倍數, 肯定不優
			if( !( d[i]%ans[j] ) ) { flg=1; break; }
		if( !flg ) Find_way( d[i] );
	}
	
	for( int i=1; i<=acnt; i++ ) Judge( i, ans[i] );
	
	for( int i=1; i<=acnt; i++ ) if( ans[i] )
		printf( "%.5lf\n", 1.0*ans[i]/1e5 );
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章