P1069 細胞分裂
題目描述
HanksHanks 博士是 BTBT ( Bio-TechBio−Tech ,生物技術) 領域的知名專家。現在,他正在為一個細胞實驗做準備工作:培養細胞樣本。
HanksHanks 博士手裏現在有 NN 種細胞,編號從 1-N1−N ,一個第 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 博士選擇哪種細胞都不能滿足要求,則輸出整數 -1−1 。
輸入輸出樣例
輸入樣例#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,0001≤N≤10000,1≤m1?≤30000,1≤m2?≤10000,1≤Si?≤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 細胞分裂