2016年藍橋杯A組 第十題 最大比例
比賽時,當我看到這道題,我徹底的懵比了,沒有思路,沒有思路,沒有思路,重要的事說三遍,賽後,也沒有在網上找別人的程式碼看,因為對省賽感覺很不好,以為自己掛了,所以沒有心情去看題,應該說是不敢去看題,成與敗,關係著我的尊嚴,當初學校不讓我報名A組,很多人都嘲諷我不知天高地厚,一個破二本的院校,還想挑戰A組;更有人反問我,你才學了幾天,到你比賽時撐死了也就學滿七個月,就這麼瞧不起B組? 實話說,我真的瞧不起B組,因為我相信自己的能力! 廢話不多說,轉入正題,對於這個題,我真的是沒有一絲的思路可言,前天我百度了一下,網上還沒有一個這道題相關的問題答案解析,沒有辦法,只能靠自己了,畢竟自己動手豐衣足食嘛。
先上題:
X星球的某個大獎賽設了M級獎勵。每個級別的獎金是一個正整數。
並且,相鄰的兩個級別間的比例是個固定值。
也就是說:所有級別的獎金數構成了一個等比數列。比如:
16,24,36,54
其等比值為:3/2
現在,我們隨機調查了一些獲獎者的獎金數。
請你據此推算可能的最大的等比值。
輸入格式:
第一行為數字N,表示接下的一行包含N個正整數
第二行N個正整數Xi(Xi<1 000 000 000 000),用空格分開。每個整數表示調查到的某人的獎金數額
要求輸出:
一個形如A/B的分數,要求A、B互質。表示可能的最大比例係數
測試資料保證了輸入格式正確,並且最大比例是存在的。
例如,輸入:
3
1250 200 32
程式應該輸出:
25/4
再例如,輸入:
4
3125 32 32 200
程式應該輸出:
5/2
再例如,輸入:
3
549755813888 524288 2
程式應該輸出:
4/1
資源約定:
峰值記憶體消耗 < 256M
CPU消耗 < 3000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include , 不能通過工程設定而省略常用標頭檔案。
苦於沒有思路,苦於網上沒有提示,只能自己想,最後,在一張廢紙上找起了規律,結果發現真的毫無規律可言,只能作罷,用最樸素的辦法解吧!
逆向思維考慮,需要求最大比例,那麼肯定要從比例入手,所以首先就是求出所有的比例,並且去重,然後就需要對這些比例進行排序來謀求最大的基數,這個基數即為最大的比例。
思路聽著很簡單,但是實現起來著實麻煩,需要考慮的細節問題賊多,不多說了,看程式碼吧,程式碼更有說服力!
程式碼C:
#include <stdio.h>
#include <math.h>
#define _MAX 1000000000000
int N, p = 0;
long long M[100], nAtor[100], dAtor[100];
double W[100];
//M原資料排序去重
void sequenceM()
{
int len = N, i , j;
for (i = 0; i < N - 1; i++)
{
for (j = i + 1; j < N; j++)
{
if (M[i] > M[j])
{
M[i] ^= M[j];
M[j] ^= M[i];
M[i] ^= M[j];
}
else if (M[i] == M[j])
{
M[j] = _MAX;
len--;
}
}
}
N = len;
// for (i = 0; i < N; i++)
// {
// printf("%lld ", M[i]);
// }
// printf("\n");
return ;
}
//約分
void reduce(int i)
{
long long j = M[i];
for (; j > 0; j--)
{
if (M[i] % j == 0 && M[i + 1] % j == 0)
{
dAtor[i] = M[i] / j;
nAtor[i] = M[i + 1] / j;
return ;
}
}
return ;
}
//W資料排序去重
void sequenceW()
{
int len = N - 1, i , j;
for (i = 0; i < N - 2; i++)
{
for (j = i + 1; j < N - 1; j++)
{
if (W[i] > W[j])
{
double tempW = W[i];
W[i] = W[j];
W[j] = tempW;
long long tempN = nAtor[i];
nAtor[i] = nAtor[j];
nAtor[j] = tempN;
long long tempD = dAtor[i];
dAtor[i] = dAtor[j];
dAtor[j] = tempD;
}
else if (W[i] == W[j])
{
W[j] = _MAX;
len--;
}
}
}
N = len;
// for (i = 0; i < N; i++)
// {
// printf("%g %lld %lld\n", W[i], nAtor[i], dAtor[i]);
// }
return ;
}
//分別求分子、分母基數
long long NDbase(long long *Ator)
{
long long flag = Ator[0];
if (N == 1)
{
return flag;
}
int i = 1, j, tag = 0; //標記flag是否為符合基數要求
for (; i < N; i++)
{
for (j = 2; pow((double)flag, (double)j) <= Ator[i]; j++)
{
if (pow((double)flag, (double)j) == Ator[i])
{
tag = 1;
break;
}
}
if (tag == 1)
{
tag = 0;
continue;
}
break;
}
if (i == N)
{
return flag;
}
tag = 0;
for (flag = Ator[0] / 2; flag > 0; flag--)
{
for (i = 0; i < N; i++)
{
for (j = 2; pow((double)flag, (double)j) <= Ator[i]; j++)
{
if (pow((double)flag, (double)j) == Ator[i])
{
tag = 1;
break;
}
}
if (tag == 1)
{
tag = 0;
continue;
}
break;
}
if (i == N)
{
return flag;
}
}
return 0;
}
//求最大基數
void base()
{
long long N, D; //最大比例的分子和分母
N = NDbase(nAtor);
D = NDbase(dAtor);
printf("%lld/%lld\n", N, D);
return ;
}
//求最大比例
void pro()
{
int i;
sequenceM();
for (i = 0; i < N - 1; i++)
{
W[i] = M[i + 1] * 1.0 / M[i];
reduce(i);
}
sequenceW();
base();
return ;
}
int main(int argc, const char * argv[])
{
int i = 0;
scanf("%d", &N);
for (; i < N; i++)
{
scanf("%lld", &M[i]);
}
pro();
return 0;
}
是不是很長啊?不要急,慢慢看吧,註釋我也寫了,希望你能懂!真不懂的話,就別看了,去做別的題吧!做這個題是在浪費時間,對很多人而言……
OVER!!!