ZSTU月赛—Problem C: 素数空间(哥德巴赫猜想+欧拉筛法)
Description
一天,小明正在搬砖,他收集了n(n<=1e7)种砖,砖的编号1-n这个时候,他突然说了一句,召唤神龙,然后,他穿越到了一个时空,发现这里的东西都是由素数组成的,这里的砖也和素数有关,他的砖也和他一块过来了,只是发生了一些变化,编号为1的砖不见了,编号为素数的砖没有发生变化,编号为合数的砖变成了编号为几块素数的砖(砖的编号和为之前的那个合数),由于这个世界能量太少,所以这些合数的砖尽可能的变成数目少的其他砖。于是小明想请教你他还有多少砖。
例如 编号为12的砖会变成编号5 7 的砖 不会变成编号2 3 2 2 3 的砖。编号9的砖会变成编号2 7 的砖 不会变成编号 3 3 3 的砖
Input
给你一个T(1<=T<=3e3)
接下来T行每行一个n(0<=n<=1e7)
Output
一共T行,每一行输出一个结果;
Sample Input
2
3
5
Sample Output
2
5
也算是通过这道题更加了解了哥德巴赫猜想,特别是三素数定理,顺便复习了一下欧拉筛法(后来试了下,其实普通筛素数也能过,代码就不贴了…)
题解:
哥德巴赫猜想:
大于二的偶数可以分解为两个素数之和;
大于七的奇数可以分解为三个素数之和;(是一定可以分解成三个素数之和,也有可能分解成两个) 分解成两个必然有一个是2,其他情况就是至少三个
多组测试要先用前缀和预处理一下。
#include<bits/stdc++.h>
#define fi first
#define se second
#define FOR(a) for(int i=0;i<a;i++)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<P,int> LP;
const ll inf=0x3f3f3f3f;
const int N=1e7+10;
const ll mod=998244353;
map<string,ll> mp;
map<string ,int>ml;
int ans[N],prime[N];
bool did[N];
int n,m,x,t,tot=0;
int main()
{
memset(did,0,sizeof did);
int tot=0;
for(int i=2;i<N;i++)
{
if(!did[i]) prime[++tot]=i,ans[i]=1;
for(int j=1;j<=tot&&i*prime[j]<=N;j++)
{
did[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
for(int i=2;i<=N;i++)
{
if(ans[i]) continue;
ans[i]=2;
if(i&1) ans[i]+=did[i-2];
}
for(int i=1;i<N;i++)
ans[i]+=ans[i-1];
scanf("%d",&n);
while(n--)
{
scanf("%d",&x);
printf("%d\n",ans[x]);
}
}
/**************************************************************
Problem: 4403
User: 2017329621071
Language: C++
Result: Accepted
Time:200 ms
Memory:89356 kb
****************************************************************/