Ural 2070 Interesting Numbers

来源:互联网 发布:json数组格式怎样写 编辑:程序博客网 时间:2024/04/30 15:06

Description

Nikolay and Asya investigate integers together in their spare time. Nikolay thinks an integer is interesting if it is a prime number. However, Asya thinks an integer is interesting if the amount of its positive divisors is a prime number (e.g., number 1 has one divisor and number 10 has four divisors).

Nikolay and Asya are happy when their tastes about some integer are common. On the other hand, they are really upset when their tastes differ. They call an integer satisfying if they both consider or do not consider this integer to be interesting. Nikolay and Asya are going to investigate numbers from segment [L, R] this weekend. So they ask you to calculate the number of satisfying integers from this segment.

Input

In the only line there are two integers L and R (2LR1012).

Output

In the only line output one integer — the number of satisfying integers from segment [L, R].

题意

Nikolay 认为一个数是有趣的,若这个数是素数;Asya 认为一个数是有趣的,当一个数的约数个数为 k ,且 k 是一个素数。

问在区间 [L,R] 中,两人同时觉得有趣或同时觉得不有趣的数的个数。

分析

首先,当一个数是素数的时候,这个数的约数个数为 2 (1 和自身),是素数;即两人必然同时认为一个素数是有趣的。

之后,考虑合数的情况。一个数约数的个数可以通过公式快速求得(套质因数分解的板):

ndivisorNum=ab11×ab22××abtottot=(b1+1)×(b2+1)×...×(btot+1)

很容易看到,当一个合数的因子数 >=2 时,这个数的约数个数必然是一个合数,则两人同时认为这个数不有趣。

因此,只需要判断一个素数的任意幂次,当 n=ab ,且 b+1 是一个素数的时候,两人的判断是不同的,将这部分数去除即可得到正确答案。

故预处理出 [1,106] 区间中的素数,并以其为底,不断获取不同幂次的值,同时判断 b+1 是否为素数。

HINT:由于最大右区间为 1012 ,任意大于 106 的数的平方即大于 1012 ,故不需要打更大的素数表。

代码

#include<bits/stdc++.h>using namespace std;const long long inf = 1e12;const int N = 1000001;bool isprime[N];int primes[N/3], tot;void getPrime() {    tot = 0;    memset(isprime, 0, sizeof(isprime));    for(int i=2, j;i<N;i++) {        if(!isprime[i]) primes[tot++] = i;        for(j=0;j<tot && i*primes[j] < N;++j) {            isprime[i*primes[j]] = true;            if(i % primes[j] == 0)  break;        }    }}int main(){    long long j, l, r;    getPrime();    vector<long long> vec;    for(int i=0, x;i<tot;i++)        for(j=(long long)primes[i]*primes[i], x=2;j<=inf;j*=primes[i], ++x)            if(!isprime[x+1])   vec.push_back(j);    sort(vec.begin(), vec.end());    scanf("%I64d %I64d",&l,&r);    int lidx = lower_bound(vec.begin(), vec.end(), l) - vec.begin();    int ridx = upper_bound(vec.begin(), vec.end(), r) - vec.begin();    printf("%I64d\n", r-l+1-(ridx-lidx));}
0 0
原创粉丝点击