题目+样例
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 (2 ≤ L ≤ R ≤ 10^12).
Output
In the only line output one integer — the number of satisfying integers from segment [L; R].
3 7
output: 4
2 2
output: 1
77 1010
output: 924
解题思路
首先题目告诉你 有两个人,大N喜欢质数不喜欢合数;大A喜欢约数【能整除】的数量为质数的,不喜欢数量不是质数的
现在给你一个区间l-r问里面有多少个他们态度一致的数【要么都喜欢,要么都不喜欢】
首先我们我们要将数拆成几个部分来分段求解
1.质数
质数的分解只有本身和1,数量2是质数,所以大家都喜欢
2.合数
合数中又要分类,首先大N是不喜欢的,那么就会出现大A匹配情况: 不喜欢-不喜欢,不喜欢-喜欢的情况;
一个合数能有多少个能整除的?这个就需要用到质因数的推论了:合数质因数分解后质因数幂+1之积【排列组合问题】
所以约数要是个数要为质数,只会出现在合数是某一个质数的n方的情况下,其他情况下质因数个数>2,约数个数是幂+1之积,一定是合数【能拆,当时我没从质数n方这个地方绕出来】
可以得到不是质数的n方的大A不喜欢
是质数的n方时,约数个数就是n+1。n+1是质数,大A喜欢;n+1不是质数,大A不喜欢。
所以我们只需要排除范围内是质数n方,n+1是质数的数字;其他情况两人态度一致
【用到的算法,欧拉筛==线性筛】
1012只需要就求出106的内的素数就行了,至于为什么因为106的平方就是1012,所以1012内质因数分解不会超过106
求出素数后就看每个素数的n方n+1是不是质数就行了,算出0-l-1区间剩下的,0-r区间剩下的,两个剩下的相减完事!orz
代码
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define ll long long
const ll N= 1e6+100;
ll num[N],prime[N],pos=0;
void init()
{
for(ll i=2;i<=N-100;i++)
{
if(!num[i])
{
prime[pos++]=i;
num[i]=i;
}
for (ll j=0;j<pos;j++)
{
if (prime[j]>num[i]||prime[j]>1.0*(N-100)/i)break;
num[prime[j]*i]=prime[j];
}
}
}
ll solve (ll x)
{
ll ans=0;
for (ll i=0;i<pos;i++)
{
ll cnt= prime[i];
cnt*=prime[i];
if (cnt>x)break;
for (ll j=2;;j++)
{
if (cnt>x)break;
if (num[j+1]==j+1) ans++;
cnt*=prime[i];
}
}
return x-ans;
}
int main ()
{
init();
ll l,r;
cin>>l>>r;
cout<<solve(r)-solve(l-1)<<endl;
return 0;
}