【計蒜客 T2059 --- 細胞分裂】公約數
Description
Hanks 博士是 BT (Bio-Tech,生物技術) 領域的知名專家。現在,他正在爲一個細胞實驗做準備工作:培養細胞樣本。
Hanks 博士手裏現在有 N 種細胞,編號從 1−N,一個第 i 種細胞經過 1 秒鐘可以分裂爲 Si 個同種細胞( Si 爲正整數)。現在他需要選取某種細胞的一個放進培養皿,讓其自由分裂,進行培養。一段時間以後,再把培養皿中的所有細胞平均分入 M個試管,形成 M 份樣本,用於實驗。Hanks 博士的試管數 M 很大,普通的計算機的基本數據類型無法存儲這樣大的 M 值,但萬幸的是,M 總可以表示爲 m1 的 m2 次方,即 M=mm21 ,其中 m1,m2 均爲基本數據類型可以存儲的正整數。
注意,整個實驗過程中不允許分割單個細胞,比如某個時刻若培養皿中有 4 個細胞,Hanks 博士可以把它們分入 2 個試管,每試管內 2 個,然後開始實驗。但如果培養皿中有 5 個細胞,博士就無法將它們均分入 2 個試管。此時,博士就只能等待一段時間,讓細胞們繼續分裂,使得其個數可以均分,或是乾脆改換另一種細胞培養。爲了能讓實驗儘早開始,Hanks 博士在選定一種細胞開始培養後,總是在得到的細胞“剛好可以平均分入 M 個試管”時停止細胞培養並開始實驗。現在博士希望知道,選擇哪種細胞培養,可以使得實驗的開始時間最早。
Input
第一行,有一個正整數 N,代表細胞種數。
第二行,有兩正整數 m1,m2,以一個空格隔開,即表示試管的總數 M=mm21.
第三行有 N 個正整數,第 i 個數 Si 表示第 i 種細胞經過 1 秒鐘可以分裂成同種
細胞的個數。
對於 50% 的數據,有 mm21≤30000。
對於所有的數據,有 1≤N≤1e4,1≤m1≤3e4,1≤m2≤1e4,1≤Si≤2e9。
Output
一個整數,表示從開始培養細胞到實驗能夠開始所經過的最少時間(單位爲秒)。
如果無論 Hanks 博士選擇哪種細胞都不能滿足要求,則輸出整數 −1。
Sample Input
1
2 1
3
Sample Output
-1
解題思路
記錄m1的m2次方中所有的公約數。當然我們只需要找m1的公約數即可,然後乘以m2,即可以減少很多計算。
然後判斷輸入的數據中是否全部包含這些公約數,並且記錄最少時間。
AC代碼(C++):
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <map>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e5+5;
const int MOD = 1e9+7;
int main(){
SIS;
int n,m1,m2,x,len,ans=inf,res;
vector<int> v,cnt;
cin >> n >> m1 >> m2;
for(int i=2;i<=m1;i++){
if(m1%i==0){
int pos=0;
v.push_back(i);
while(m1%i==0) m1/=i,pos++;
cnt.push_back(pos*m2);
}
}
len=v.size();
while(n--){
res=0;
cin >> x;
for(int i=0;i<len;i++){
if(x%v[i]!=0){
res=inf;
break;
}
int num=0;
while(x%v[i]==0) num++,x/=v[i];
if(cnt[i]%num==0) res=max(res,cnt[i]/num);
else res=max(res,cnt[i]/num+1);
}
ans=min(ans,res);
}
if(ans==inf) cout << -1 << endl;
else cout << ans << endl;
return 0;
}