Loading

CF17A Noldbach problem 题解

CF17A Noldbach problem 题解

传送门

题目分析

这道题需要运用素数筛的知识。

我们可以用数组 \(prime\) 来存储在 \(2\)~\(n\) 中所有的素数。存储素数可以用线性筛素数。

void primes(int n)
{
	memset(v,0,sizeof(v));//最小质因子
	cnt=0;//质数个数
	for(int i=2;i<=n;i++)
	{
		if(!v[i])//未被标记,i为质数
		{
			v[i]=i;
			prime[++cnt]=i;
		}
		for(int j=1;j<=cnt;j++)
		{
			if(prime[j]>v[i]||prime[j]>n/i) break;//i有更小的质因子,或者超出n的范围
			v[i*prime[j]]=prime[j];//prime[j]为合数 i*prime[j]的最小质因子
		}
	}
}

之后,我们要判断这些素数里哪些是“好素数”。“好素数”是在数值比它小的素数中,只要能找到两个相邻的素数,且这两个相邻素数之和+1 等于 “好素数”的数值,那么它就是好素数。

由于数据范围 \(2\leq n\leq 1000\) ,所以我们可以用 \(O(n^2)\) 来暴力搜出来好素数。只要搜到,就把它存入数组 \(x\) 中。

for(int i=3;i<=cnt;++i)
		for(int j=1;j<=i-2;++j) 
		{
			if(prime[j]+prime[j+1]+1 == prime[i])
			x[++tot]=prime[i];
		}

最后,我们只要判断 \(x\) 数组存储的数的个数是否大于 \(k\) 即可。

这道题还有一些细节,详见代码部分。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int n,k,cnt,ans,prime[1005],tot=0;
int x[1005],v[1005];

void primes(int n)//线性筛素数
{
	memset(v,0,sizeof(v));//最小质因子
	cnt=0;//质数个数
	for(int i=2;i<=n;i++)
	{
		if(!v[i])//未被标记,i为质数
		{
			v[i]=i;
			prime[++cnt]=i;
		}
		for(int j=1;j<=cnt;j++)
		{
			if(prime[j]>v[i]||prime[j]>n/i) break;//i有更小的质因子,或者超出n的范围
			v[i*prime[j]]=prime[j];//prime[j]为合数 i*prime[j]的最小质因子
		}
	}
}

int main()
{
	memset(x,0x3f3f3f,sizeof x);
    /*
    这里把x初始化为一个很大的值,因为最后要判断n和x数组的大小。
    如果x数组中的数都小于n,则下一个数需要为一个最大值,以记录答案个数。
    */
	cin>>n>>k;
	primes(n);	//线性筛素数
	
	for(int i=3;i<=cnt;++i)
		for(int j=1;j<=i-2;++j) 
		{
			if(prime[j]+prime[j+1]+1 == prime[i])
			x[++tot]=prime[i]; //筛出“好素数”
		}
		
	for(int i=1;i<=tot+1;++i)
	if(x[i]>n) 
	{
		ans=i-1; //判断在范围内有几个“好素数”
		break;
	}
	
	if(ans>=k) cout<<"YES"; //最后和k作比较,输出答案
	else cout<<"NO";
}
posted @ 2020-09-20 09:00  EdisonBa  阅读(113)  评论(0编辑  收藏  举报