Solution
看题和 \(\gcd\) 有关系,所以我们可以先考虑一下质数,然后发现对于质数 \(x\) ,当他不 \(lonely\) 即满足条件的时候,是 \(x^2\) 出现的时候,因为 \(x+1>x,x+x>1\) 。
现在考虑合数,分两种情况,一种是形似 \(p^2\) 的( \(p\) 是质数),因为 \(p^2\) 能使 \(p\) 不孤独,所以 \(p^2\) 自己也是不孤独的;另一种是剩下的,设 \(a,c\) 为其中任意的两个数( \(a>c\) ), \(b\) 为 \(gcd(a,c)\) 且 \(1<b<\sqrt a\),那么我们构造出一个 \(c\) 满足条件: \(\frac ab+b>\frac cb,\frac ab+\frac cb>b,\frac cb+b>\frac ab\) 即可。
因为 \(a>c\) 所以 \(\dfrac ab+b>\dfrac cb\) 显然满足,因为 \(b<\sqrt a\) ,所以 \(\dfrac cb+\dfrac ab>b\) 也满足。对于剩下的条件我们只要能证明必有一个 \(\dfrac cb\) 满足 \(\dfrac cb>\dfrac ab-b,\dfrac cb<\dfrac ab\) 。因为 \(b>1\) ,所以在 \((\dfrac ab-b)\) ~ \(\dfrac ab\) 起码有一个数字满足 \(\dfrac cb\) 的条件。
我们已经考虑完所有情况,发现只有一个质数的平方没有出现在前 \(n\) 数中时,这个质数才会被统计进答案。
说的简单一点:设 \(sum_i\) 为前 \(i\) 数中的质数的数量,那么答案就是 \(sum_n-sum_{\lfloor \sqrt n\rfloor}\)
代码
# include <iostream>
# include <cstdio>
# include <cmath>
# define MAXN 1000010
using namespace std;
inline void read(int & x){
x = 0; int ch = getchar();
for( ;!isdigit(ch); ch = getchar());
for( ; isdigit(ch); ch = getchar()){
x = x * 10 + ch - '0';
}
}
int cntP = 0, prime[MAXN], sum[MAXN];
bool notP[MAXN];
int main(){
int t;
read(t);
notP[0] = notP[1] = 1;
for(int i = 2; i <= 1000000; i++){
if(!notP[i]){
prime[++cntP] = i;
}
for(int j = 1; j <= cntP && i * prime[j] <= 1000000; j++){
notP[i * prime[j]] = 1;
if(!(i % prime[j])){
break;
}
}
}
for(int i = 1; i <= 1000000; i++){
sum[i] = sum[i-1] + (!notP[i]);
}
for(int n; t; t--){
read(n);
printf("%d\n", sum[n] - sum[(int)sqrt(n)] + 1);
}
return 0;
}
(这个代码不是我的,是和我一个团队打比赛的同学的,本人代码锅了)