链接:
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定一个正整数 p 求一个最小的正整数 n,使得 n! 是 p 的倍数
输入描述:
第一行输入一个正整数T表示测试数据组数 接下来T行,每行一个正整数p
输出描述:
输出T行,对于每组测试数据输出满足条件的最小的n
示例1
输入
4
1
2
4
8
输出
1
2
4
4
备注:
T≤103,p≤109
题解:
两个方法:
二分与贪心
在什么条件下n!会是p的倍数呢?
n!的素因子集合包含p的素因子集合,也就是对于每个质因子,阶乘n中的数量大于对应p中的数量
贪心:
暴力做法,从2开始循环质因数,对于每次一个质因数i,看p1当前能分解出多少个,然后再枚举n,看n最小为多少能做到质因数i的数量大于等于p1
代码中有句sum=max(sum,j);什么含义?你想如果我们之前求出n=9包含3的数量满足条件,那枚举5时得到n=10,10的阶乘是包含9的阶乘,也就是10!既满足质因数2也满足3,所以求最大max
代码内也有注释
代码:
#include<bits/stdc++.h>
using namespace std;
int main() {int t,p1,sum=0;cin>>t;while(t--) {cin>>p1;sum=0;for(int i=2;i*i<=p1;++i)if(p1%i==0) {int cnt=0;while(p1%i==0) {p1/=i;++cnt;}//当前质因子i在p1中的数量 int tmp=0;int j;for(j=i;;j+=i) {int n=j;while(n%i==0){n/=i;++tmp;} //记录当前质因数在n中的数量 if(tmp>=cnt) break;//找到一个数,使得他的质因数i的数量多于等于p1 }sum=max(sum,j); // cout<<sum<<endl;}cout<<max(sum,p1)<<endl;}
}
二分:
其实就是把方法一中暴力的过程改成更为巧妙的二分过程,先将p1的质因数存入数组prime,然后二分查找,寻找最小的n,满足他的质因数i的数量多于等于p1
代码借鉴其大佬博客写的
代码:
#include <bits/stdc++.h>
using namespace std;const int maxn = 1e5 + 3;
int prime[maxn], cnt[maxn], len = 0;
//素因子,素因子的个数,数组长度int judge(int mid) {for (int i = 1; i <= len; i++){int n = midint sum = 0;while (n) {sum += n / prime[i];n /= prime[i];}if (sum < cnt[i]) return 0;//不满足条件就找下一个n }return 1;//满足要求
}
int main() {int T; cin>>T;int l,r,sum; while (T--) {int p1;cin>>p1;len = 0;memset(cnt, 0, sizeof cnt);for (int i = 2; i * i <= p1; i++)if ( p1 % i==0) {prime[++len] = i;while (p1 % i==0) {cnt[len]++;p1 /= i;}}if (p1 > 1) {prime[++len] = p1;cnt[len]++;}//求出素因子及其个数l = 1, r = 1e9, sum = 0;while (l <= r) {int mid = l + r >> 1;if (judge(mid)) {r = mid - 1;sum = mid;}else l = mid + 1; }//二分查找printf("%d\n", sum);}return 0;
}