1. 程式人生 > >cogs 466. [NOIP2009] 細胞分裂

cogs 466. [NOIP2009] 細胞分裂

次數 博士 空格 ble 其中 esp 因數 cin 輸入輸出

466. [NOIP2009] 細胞分裂

★★ 輸入文件:cell.in 輸出文件:cell.out 簡單對比
時間限制:1 s 內存限制:128 MB

【問題描述】
Hanks 博士是BT (Bio-Tech,生物技術) 領域的知名專家。現在,他正在為一個細胞實驗做準備工作:培養細胞樣本。
Hanks 博士手裏現在有N 種細胞,編號從1~N,一個第i 種細胞經過1 秒鐘可以分裂為Si 個同種細胞(Si 為正整數)。現在他需要選取某種細胞的一個放進培養皿,讓其自由分裂,進行培養。一段時間以後,再把培養皿中的所有細胞平均分入M 個試管,形成M 份樣本,用於實驗。Hanks 博士的試管數M 很大,普通的計算機的基本數據類型無法存儲這樣大的 M 值,但萬幸的是,M 總可以表示為m1 的m2 次方,即 M = m1m2 ,其中m1,m2 均為基本數據類型可以存儲的正整數。


註意,整個實驗過程中不允許分割單個細胞,比如某個時刻若培養皿中有4 個細胞,Hanks 博士可以把它們分入2 個試管,每試管內2 個,然後開始實驗。但如果培養皿中有5個細胞,博士就無法將它們均分入2 個試管。此時,博士就只能等待一段時間,讓細胞們繼續分裂,使得其個數可以均分,或是幹脆改換另一種細胞培養。
為了能讓實驗盡早開始,Hanks 博士在選定一種細胞開始培養後,總是在得到的細胞“剛好可以平均分入M 個試管”時停止細胞培養並開始實驗。現在博士希望知道,選擇哪種細胞培養,可以使得實驗的開始時間最早。
【輸入】
輸入文件名為 cell.in,共有三行。
第一行有一個正整數 N,代表細胞種數。

第二行有兩個正整數 m1,m2,以一個空格隔開,m1m2 即表示試管的總數M。
第三行有 N 個正整數,第i 個數Si 表示第i 種細胞經過1 秒鐘可以分裂成同種細胞的個數。
【輸出】
輸出文件 cell.out 共一行,為一個整數,表示從開始培養細胞到實驗能夠開始所經過的最少時間(單位為秒)。如果無論 Hanks 博士選擇哪種細胞都不能滿足要求,則輸出整數-1。
【輸入輸出樣例 1】
cell.in

1
2 1
3

cell.out

-1
【輸入輸出樣例1 說明】
經過 1 秒鐘,細胞分裂成3 個,經過2 秒鐘,細胞分裂成9 個,……,可以看出無論怎麽分裂,細胞的個數都是奇數,因此永遠不能分入2 個試管。

【輸入輸出樣例 2】
cell.in

2
24 1
30 12

cell.out

2
【輸入輸出樣例2 說明】
第 1 種細胞最早在3 秒後才能均分入24 個試管,而第2 種最早在2 秒後就可以均分(每試管144/(241)=6 個)。故實驗最早可以在2 秒後開始。
【數據範圍】
對於 50%的數據,有m1m2 ≤ 30000。
對於所有的數據,有1 ≤N≤ 10000,1 ≤m1 ≤ 30000,1 ≤m2 ≤ 10000,1 ≤ Si ≤ 2,000,000,000。

思路:質因數分解。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int s[10001],zs[10001];
int n,m1,m2,mz,t=2,c,ans=0x7fffffff,l;
int main(){
    freopen("cell.in","r",stdin);
    freopen("cell.out","w",stdout);
    cin>>n>>m1>>m2;
    for(int i=1;i<=n;i++) cin>>s[i];
    if(m1==1){
        cout<<0<<endl;
        return 0;
    }
    while(m1!=1){
        while(!(m1%t)){
            m1/=t;
            zs[t]++;
        } 
        mz=max(mz,t);
        zs[t++]*=m2;
    }
    for(int i=1;i<=n;i++){
        l=0;
        for(int j=2;j<=mz;j++){
            if(!zs[j]) continue;
            c=0;
            while(!(s[i]%j)){
                s[i]/=j;
                c++;
            } 
            if(!c){
                l=0x7fffffff;
                break;
            }
            l=max(l,(zs[j]-1)/c);//算次數差
        }
        ans=min(ans,l);
    }
    cout<<(ans==0x7fffffff?-1:ans+1)<<endl;//一定記住要+1,血的教訓啊!!!
    return 0;
}

cogs 466. [NOIP2009] 細胞分裂