原題連結:https://www.luogu.com.cn/problem/P1069
題意解讀:一個數s代表細胞經過一天分裂的個數,則經過t天后個數為st,要計算經過幾天后能整除m1m2,也就是st % m1m2 == 0,有多個s,要計算天數最少就可以滿足條件的。
解題思路:
直接求st % m1m2顯然不可取,會超出整數最大範圍,高精度也不是好辦法。
對於這種情況,可以分解質因數
以樣例2為例:
m1 = 24, m2 = 1,m1m2 = 23*31
s = 30時,st = (21*31*51)t = 2t*3t*5t,要能整除m1m2 = 23*31, 2t>=23, 3t>=31, t至少是3,也就是max(3/1, 1/1)
s = 12時,st = (22*31)t = 22t*3t,要能整除m1m2 = 23*31,22t>=23,3t>=31, t至少是2,也就是max(⌈3/2⌉,1/1),注意3/2上取整
再看樣例1:
m1 = 2, m2 = 1, m1m2 = 21
s = 3時,st = 31,由於m1m2 = 21的質因數中有2,而s的質因數中沒有2,所以st永遠也不可能整除21
根據上面的分析,解法就比較明確了:
1、對m1^m2分解質因數,主要是對m1分解質因數,m2乘上各個質因數的指數,作為最終的指數即可
質因數用vector<int> pm儲存,對應的指數用vector<int> px儲存。
2、再對每一個s進行處理,同樣對s分解質因數,這次用hash陣列儲存int ps[30005],
因為m1最大30000,其質因數也不超過30000,因此s的質因數超過30000的不必要關心,只看跟m1一致的質因數即可。
ps[i] = cnt存的是s的質因數i的指數為cnt。
3、對m1^m2的每一個質因數,去s的質因數里找,
如果找不到,說明s^t永遠也無法整除m1^m2;
如果能找到,就計算res = ⌈m1^m2的指數 / s的指數⌉ ,找res最大的就是改s經過多少天能整除m1^m2
4、對求得的多個res,取最小值
5、如果每個s都無法整除m1^m2,則輸出-1
100分程式碼:
#include <bits/stdc++.h>
using namespace std;
int n, m1, m2;
int s;
vector<int> pm; //m1^m2的質因數
vector<int> px; //prims裡每個質因數的指數
int ps[30005]; //s的質因數對應的指數
int ans = INT_MAX;
int main()
{
cin >> n >> m1 >> m2;
//對m1^m2分解質因數
for(int i = 2; i * i <= m1; i++)
{
if(m1 % i == 0)
{
int cnt = 0;
while(m1 % i == 0)
{
cnt++;
m1 /= i;
}
pm.push_back(i);
px.push_back(cnt * m2);
}
}
if(m1 > 1)
{
pm.push_back(m1);
px.push_back(m2);
}
for(int i = 1; i <= n; i++)
{
cin >> s;
//對每一個s分解質因數,不考慮超過m1的質因數
memset(ps, 0, sizeof(ps));
for(int j = 2; j * j <= s && j <= 30000; j++)
{
if(s % j == 0)
{
int cnt = 0;
while(s % j == 0)
{
cnt++;
s /= j;
}
ps[j] = cnt;
}
}
if(s > 1 && s <= 30000) ps[s] = 1;
int res = 0; //如果m1=1,只需要0天就可以乘除1
bool success = true;
//檢查m1的每個質因數
//如果有質因數在s的質因數中不存在,表示不能滿足要求
//如果質因數都存在,計算m1的質因數指數 / s的中相同質因數指數,向上取整,最大的結果即需要的時間
for(int j = 0; j < pm.size(); j++)
{
if(ps[pm[j]] == 0) //如果有m1的質因數在s中不存在
{
success = false;
break;
}
else
{
int low = ps[pm[j]];
int high = px[j];
int cnt = high / low;
if(high % low != 0) cnt++;
res = max(res, cnt); //找每個質因數要增長天數最大的一個
}
}
if(success) ans = min(ans, res); //多個時間取最小值
}
if(ans == INT_MAX) cout << -1;
else cout << ans << endl;
return 0;
}