想她一次就背十個單詞,當我英語過六級後,我就去告訴她,我很在意她
一天一道數論題,當我可以秒殺數論題的時候,就開始做 DP
劃重點:
以後每天都會更新一道數論題,有興趣的小夥伴可以關注一下,共同進步~~~
———————————————— 不正經的分界線 ————————————————
今日份快樂:洛谷 P1069 傳送門
明日份快樂:洛谷 P1082 傳送門
———————————————— 很正經的分界線 ————————————————
題目大意
博士要培養細菌平均裝到 M 個試管中去做實驗。M 很大,一般的數據類型裝不下它。碰巧的是,M 正好可以分成 m1m2 的形式。
一共有 n 種細菌,對於每個第 i 種細菌,每天都可以分裂成 Si 個細菌。給出 m1 、m2 、n 和 對應的 Si。
問:最快什麼時候可以去做實驗
分析
就是找 Si 什麼時候可以變成 M 的倍數
大佬們讀完題就知道要質因數分解了,我這個菜雞想了好久
質因數分解:任意的大於1 的整數都一定可以分解成質數冪乘積的形式
數學表達式爲:n = 2x1 * 3x2 * 5x3 * 7x4……(x1,x2,x3…會根據 n 的不同而改變)
舉個栗子:
對於樣例【二】
2
24 1
30 12
我們先對 M 進行質因數分解得到
M = 2 3 * 3 1
接下來我們模擬一下細菌的增值過程,看錶
-------- | 第一天 | 第二天 | 第三天 | 第四天 |
---|---|---|---|---|
一號 | 30 | 900 | 27000 | 810000 |
二號 | 12 | 144 | 1728 | 20736 |
好像看不出來啥,我們換個形式
-------- | 第一天 | 第二天 | 第三天 | 第四天 |
---|---|---|---|---|
一號 | 2 1* 31 * 51 | 2 2 * 3 2 * 5 2 | 2 3 * 3 3 * 5 3 | 2 4 * 3 4 * 5 4 |
二號 | 22 * 31 | 24 * 32 | 26 * 33 | 28 * 3 4 |
對比 M = 2 3 * 3 1
一號細菌在第三天的時候可以整除 M
二號細菌在第二天的時候可以整除 M
答案就是 2 了
我們應該可以看出來,對於一個細菌,如果經過增值可以被均分成 M 份,那麼這個細菌對應的 Si 的質因子一定全部包含 M 全部的質因子
解題思路
step1:篩選出來所有的質數
step2:找 M 的質因子,同時遍歷待選細菌,如果細菌不能被 M 的質因數整除這個細菌就不會增值成 M 的倍數
step3:遍歷待選細菌,選出最佳答案。如果這時候沒有待選細菌,就輸出 -1
代碼
#include <bits/stdc++.h>
using namespace std;
typedef struct Node{
int num; // 質因數
int sum; // 次冪
}node;
int pr[5000];
bool flag[30005];
int num = 0;
void Init(){ // 篩選質數
for(int i = 2; i < 30000; i++){
if(!flag[i]) pr[num++] = i;
for(int j = 0; j < num; j++){
if(pr[j] * i > 30005) break;
flag[pr[j] * i] = true;
if(i % pr[j] == 0) break;
}
}
}
int main(){
ios::sync_with_stdio(false);
Init();
ll n;
cin >> n;
ll m1, m2;
cin >> m1 >> m2;
queue<ll>v; //存待選的細菌
ll b;
for(int i = 1; i <= n; i++){
cin >> b;
v.push(b);
}
vector<node>v1; // 存 m1^m2 的質分解的結果
for(int i = 0; m1 != 1; i++){
if(m1 % pr[i] == 0){ //如果 pr[i] 是 m1^m2 的質因子就存起來
node a = {pr[i], 0};
while(m1 % pr[i] == 0){ // 算一下是多少次冪
m1 /= pr[i];
a.sum++;
}
a.sum *= m2; // 別忘了 m2
v1.push_back(a);
int len = v.size();
for(int j = 1; j <= len; j++){ // 順便判斷待選細菌符合不符合
int c = v.front(); //從隊列中拿出來
v.pop();
if(c % pr[i] == 0) v.push(c); //符合就再放回去
}
}
}
if(v.empty()) cout << -1 << endl; // 如果已經沒有待選的答案,就輸出 -1
else{
ll res = INF;
int len = v.size();
for(int i = 1; i <= len; i++){ // 尋找最佳答案
int c = v.front();
ll temp = 0;
for(int j = 0; j < v1.size(); j++){ // 遍歷 m1^m2 的質因子
ll sum = 0;
while(c % v1[j].num == 0){
sum++;
c /= v1[j].num;
}
temp = max(temp, (v1[j].sum + sum - 1) / sum);
}
res = min(temp, res);
v.pop();
}
cout << res << endl;
}
return 0;
}
如果有解釋不清楚的地方,歡迎留言
堅持的時候很狼狽,等你成功以後,醜的還是醜的 🤭