1. 程式人生 > >P1069 細胞分裂

P1069 細胞分裂

|| def ont 包含 輸入格式 HA max ans pst

題目描述

HanksHanks 博士是 BTBT ( Bio-TechBioTech ,生物技術) 領域的知名專家。現在,他正在為一個細胞實驗做準備工作:培養細胞樣本。

HanksHanks 博士手裏現在有 NN 種細胞,編號從 1-N1N ,一個第 ii 種細胞經過 11 秒鐘可以分裂為 S_iSi? 個同種細胞( S_iSi?為正整數)。現在他需要選取某種細胞的一個放進培養皿,讓其自由分裂,進行培養。一段時間以後,再把培養皿中的所有細胞平均分入 MM 個試管,形成 MM 份樣本,用於實驗。 HanksHanks 博士的試管數 MM 很大,普通的計算機的基本數據類型無法存儲這樣大的 MM 值,但萬幸的是, MM 總可以表示為 m_1m1?m_2m2? 次方,即 M = m_1^{m_2}M=m1m2?? ,其中 m_1,m_2m1?,m2? 均為基本數據類型可以存儲的正整數。

註意,整個實驗過程中不允許分割單個細胞,比如某個時刻若培養皿中有 44 個細胞,

HanksHanks 博士可以把它們分入 22 個試管,每試管內 22 個,然後開始實驗。但如果培養皿中有 55 個細胞,博士就無法將它們均分入 22 個試管。此時,博士就只能等待一段時間,讓細胞們繼續分裂,使得其個數可以均分,或是幹脆改換另一種細胞培養。

為了能讓實驗盡早開始, HanksHanks 博士在選定一種細胞開始培養後,總是在得到的細胞“剛好可以平均分入 MM 個試管”時停止細胞培養並開始實驗。現在博士希望知道,選擇哪種細胞培養,可以使得實驗的開始時間最早。

輸入輸出格式

輸入格式:

第一行,有一個正整數 NN ,代表細胞種數。

第二行,有兩個正整數 m_1,m_2m1?,m2? ,以一個空格隔開,即表示試管的總數 M = m_1^{m_2}M=m1m2?? .

第三行有 N 個正整數,第 i 個數 Si表示第 i 種細胞經過 1 秒鐘可以分裂成同種細胞的個數。

輸出格式:

一個整數,表示從開始培養細胞到實驗能夠開始所經過的最少時間(單位為秒)。

如果無論 HanksHanks 博士選擇哪種細胞都不能滿足要求,則輸出整數 -11 。

輸入輸出樣例

輸入樣例#1:
1 
2 1 
3
輸出樣例#1:
-1
輸入樣例#2:
2
24 1
30 12
輸出樣例#2:
2

說明

【輸入輸出說明】

經過 11 秒鐘,細胞分裂成 33 個,經過 22 秒鐘,細胞分裂成 99 個,……,可以看出無論怎麽分裂,細胞的個數都是奇數,因此永遠不能分入 22 個試管。

【輸入輸出樣例 22 說明】

11 種細胞最早在 33 秒後才能均分入 2424 個試管,而第 22 種最早在 22 秒後就可以均分(每試管 144/(241)=6144/(241)=6個)。故實驗最早可以在 22 秒後開始。

【數據範圍】

對於 50%的數據,有 m_1^{m_2} ≤ 30000m1m2??30000 。

對於所有的數據,有 1 ≤N≤ 10000,1 ≤m_1 ≤ 30000,1 ≤m_2 ≤ 10000,1 ≤ S_i ≤ 2,000,000,0001N10000,1m1?30000,1m2?10000,1Si?2,000,000,000 。

NOIP 2009 普及組 第三題

Solution:

  普及組的題目都有毒啊,ZYYS。

  題意很簡單,就是求滿足$s^k|{m_1}^{m_2}$條件的$k_{min}$的值。

  那麽我們很容易想到,滿足條件的前提是$s_i$包含$m_1$的所有質因子。

  於是我們直接篩出$m_1$的所有質因子並統計它們各自在${m_1}^{m_2}$中出現的次數,然後每次讀入$s$,判斷其是否可行,可行的話就求出$s$滿足條件的最小的$k$,顯然必須使得$s^k$的所有質因子各自出現的次數都大於等於${m_1}^{m_2}$中各質數出現的次數,所以$k=max(\lceil{\frac{tot_p}{num_p}}\rceil)$,其中$num_p$為$s$的質因子中素數$p$出現的次數,然後更新答案$ans=min(ans,k)$,輸出就好了。

代碼:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 using namespace std;
 7 const int N=10005;
 8 ll n,m1,m2,s,tot[N],prime[N],cnt;
 9 
10 il int gi(){
11     int a=0;char x=getchar();
12     while(x<0||x>9)x=getchar();
13     while(x>=0&&x<=9)a=(a<<3)+(a<<1)+x-48,x=getchar();
14     return a;
15 }
16 
17 int main(){
18     n=gi(),m1=gi(),m2=gi();
19     ll p=m1,ans=-1;
20     for(int i=2;i*i<=m1;i++){
21         if(p%i==0){
22             prime[++cnt]=i;
23             while(p%i==0&&p){
24                 tot[cnt]++;
25                 p/=i;
26             }
27         }
28         if(p==1)break;
29     }
30     if(p!=1)tot[++cnt]++,prime[cnt]=p;
31     For(i,1,cnt) tot[i]*=m2;
32     while(n--){
33         s=gi();
34         bool f=0;
35         For(i,1,cnt) if(s%prime[i]!=0){f=1;break;}
36         if(f)continue;
37         ll lst=0,sum;
38         For(i,1,cnt) {
39             sum=0;
40             while(s%prime[i]==0)sum++,s/=prime[i];
41             if(!sum)break;
42             if(tot[i]%sum==0)lst=max(lst,tot[i]/sum);
43             else lst=max(lst,tot[i]/sum+1);
44         }
45         if(ans==-1)ans=lst;
46         else ans=min(ans,lst);
47     }
48     cout<<ans;
49     return 0;
50 }

P1069 細胞分裂