UVA10539 Almost Prime Numbers \color{green}{\texttt{UVA10539 Almost Prime Numbers}} UVA10539 Almost Prime Numbers
[Problem] \color{blue}{\texttt{[Problem]}} [Problem]
-
给定两个数 L , R ( 1 ≤ L < R ≤ 1 0 12 ) L,R(1 \leq L < R \leq 10^{12}) L,R(1≤L<R≤1012)。
-
统计区间 [ L , R ] [L,R] [L,R](包括 L L L 和 R R R)中有多少个数满足:
- 本身不是素数
- 只有一个素因子
[Soluntion] \color{blue}{\texttt{[Soluntion]}} [Soluntion]
仔细思考一下就可以发现:本题其实就是求 [ L , R ] [L,R] [L,R] 中有多少个数,是一个素数的 a a a 次幂,其中 a a a 为大于 1 1 1 的整数。
为什么呢?第一,它本身不是素数,所以不能是素数的一次幂。第二,它不是是一个素数的幂,否则,如果它肯定不止一个素因子。
所以,我们筛出 [ 1 , 1 × 1 0 6 ] [1,1\times 10^6] [1,1×106] 中所有的素数,然后利用它们即可在很短的时间内求出解。
[code] \color{blue}{\texttt{[code]}} [code]
const int N=1e6+100;
const int M=1e5+100;
int prime[M],tot;//素数表
bool is_prime[N];//是否为素数
inline void get_all_prime(int N){
for(register int i=1;i<=N;i++)
is_prime[i]=true;//初始化
is_prime[0]=is_prime[1]=tot=0;
for(register int i=2;i<=N;i++)
if (is_prime[i]){//不是素数免谈
prime[++tot]=i;//加入素数表
for(register int j=i;j<=N/i;j++)
is_prime[i*j]=false;//update
}
}
typedef long long ll;//简写
inline int count(ll l,ll r){
int ans=0;//初始化答案为0
for(int i=1;i<=tot;i++){
ll begin=1ll*prime[i]*prime[i];
for(ll j=begin;j<=r;j*=prime[i])
if (j>=l) ans++;//找到一个答案
}
return ans;//返回答案
}
int test_number;ll l,r;
int main(){
get_all_prime(1000000);
scanf("%d",&test_number);
while (test_number--){
scanf("%lld%lld",&l,&r);
printf("%d\n",count(l,r));
}
return 0;
}