想她一次就背十个单词,当我英语过六级后,我就去告诉她,我很在意她
一天一道数论题,当我可以秒杀数论题的时候,就开始做 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;
}
如果有解释不清楚的地方,欢迎留言
坚持的时候很狼狈,等你成功以后,丑的还是丑的 🤭