ABC280D题解
修改日志
:修改了时间复杂度。
思路
核心算法:二分
一:分解质因数
首先,对输入的 ,进行分解质因数,若分解后质数 有 个,则 。
质因数的枚举
显然不能暴力。
但是,对于一个正整数 ,只要 枚举到 即可,因为如果 ,那么 一定 ,那这一定会在之前除掉了。
所以以只要在 内枚举 即可
对于每个 ,做如下的事情:
while(K2%i==0) K2/=i,sum[i]++;
这里的 就是 , 的初值是 (由于 要做边界)。
最后,如果 ,则输出 ,结束程序。(因为这个 一定是质数)
分解质因数代码:
long long K2=k;
for(long long i=2;i<=sqrt(k)+100;i++){
while(K2%i==0) K2/=i,sum[i]++;
}
if(K2!=1) return !printf("%lld\n",K2);
二:二分答案
Q:为什么能用二分?
A:因为答案满足单调性。
Q:具体点?
A:你自己往下看吧!
因为如果一个正整数 满足 的阶乘是 的倍数,那么 的阶乘一定也是 的倍数,满足单调性,可以二分。
定义左边界为 ,右边界为 ,初值:(稍微大一点,其实没必要,因为 的阶乘一定是 的倍数)。
对于每个 ,用 一 的分解质因数的方法输出数组 ,在将 和 作比较,如果有任意一个 使得 ,就将 ,否则将 。
最后输出 即可
时间复杂度:
代码(语言:c++,仅供参考,不可抄袭)
#include<bits/stdc++.h>
using namespace std;
long long k,sum[1001000],l=1,r;
int main(){
scanf("%lld",&k);
long long K2=k;
for(long long i=2;i<=sqrt(k)+100;i++){
while(K2%i==0) K2/=i,sum[i]++;
}
if(K2!=1) return !printf("%lld\n",K2);
r=k+100;
while(l<r-1){
long long mid=l+r>>1,now=mid;
bool f=0;
for(long long i=2;i<=sqrt(k)+100;i++){
long long p=i,s=0;
while(p<=mid){
s+=mid/p;
p*=i;
}
if(sum[i]>s){
f=1;
break;
}
}
if(f) l=mid;
else r=mid;
}
return !printf("%lld",r);
}

浙公网安备 33010602011771号