1. 程式人生 > >2016年藍橋杯A組 第十題 最大比例

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!!!