https://ac.nowcoder.com/acm/contest/4784/B
给定一个正整数 p
求一个最小的正整数 n,使得 n ! 是 p 的倍数
输入描述:
第一行输入一个正整数 T 表示测试数据组数
接下来 T 行,每行一个正整数 p
输出描述:
输出 T 行,对于每组测试数据输出满足条件的最小的 n
比赛思路:
比赛的时候思路错了,还以为考的是高精度,因为感觉阶乘会很大… 所以一开始把把每个数的阶乘递推 存到邻接表里,这样就可以存很大的数然后每次遍历数组看能不能整除p,最后输出数组下标i就好了…实际就是个假的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const double eps=1e-8;
ll x,y,z,n,k,t,m,p,maxs=0;
template<typename T>inline void read(T &x){
x=0; int f=1;char c=getchar();
while(c<'0'||c>'9') if(c=='-') f=-1,c=getchar();
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x*=f;
}
int check(int x,int y,int cnt){
int ans=0;
while(x){
ans+=x/y;
x/=y;
}
return ans>=cnt;
}
ll bi(int x, int cnt) {
int left = 1, right = 1e9;
while(left <= right) {
int mid = (left + right) >> 1;
if(check(mid, x, cnt)) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return right+1;
}
int main(){
// ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
read(t);
while(t--){
read(p);
ll ans=0;
for(int i=2;i*i<=p;i++){
if(p%i==0){
ll cnt=0;
while(p%i==0){
p/=i;
cnt++;
}
ans=max(ans,bi(i,cnt));
}
}
ans=max(ans,p);
printf("%lld\n",ans);
}
}
题解思路:
利用类似于埃式筛法的思想,将p进行质因数分解,
每次看能被 i 除几次,然后进入函数bi,bi函数就是进行二分的函数,找n,看看他的阶乘里有多少个因子i ,
如果当前的n里的因子i的数目大于cnt,那么就缩小范围,
函数check的作用就是找n!里因子的个数,
最后找到符合n!里的因子数>=cnt的最小的 n。
然后每次max更新答案,
这样子得到的n才能满足所有的因子数都 >= cnt。
最后还有一步:
ans=max(ans,p);
如果p=1的话就进入不了循环,这样直接ans=p=1了;
如果p为质数的话,就没有任何因子,所以最小的ans=p,只有p!才能是p的倍数
扫描二维码关注公众号,回复:
10510046 查看本文章