CF1423K Lonely Numbers

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;
}

(这个代码不是我的,是和我一个团队打比赛的同学的,本人代码锅了

上一篇:对于对数换底公式的证明


下一篇:在开发项目安装依赖时(npm install) 往往会报 npm ERR! cb()never called!的错误