题目
一天蒜头君猜想,是不是所有的偶数(除了 22),都可以用两个质数相加得到呢?于是聪明的蒜头君就找你来验证了。
输入格式
第一行输入一个整数 t 表示测试组数。
接下来 t 行,每行一个整数 n。
输出格式
输出两个整数,因为答案可能有多个,所有要求输出的这两个整数是所有答案中字典序最小的。
数据范围
对于 30% 的数据 1 ≤ t ≤ 10^3。
对于 60% 的数据 1 ≤ t ≤ 10^5。
对于 100% 的数据 1 ≤ 10^6, 4 ≤ n ≤ 10^6 ,n 为偶数。
样例输入
3
4
8
20
样例输出
2 2
3 5
3 17
本题中由于数据较大,我们可以考虑使用线性筛选质数的方法存入表中,最后再进行查表。
打表及存入的代码如下:
void data()
{
ms(a),ms(b);
for(int i=1;i<=1e6;i++)
for(int j=i;j<=1e6;j+=i)
a[j]++;
for(int i=1;i<=1e6;i++)
if(a[i]==2){
b[l++]=i;
}
}
题目的要求是让我们找出相加等于n的两个质数,不妨采用枚举的方法,先枚举出一个质数i,并在表中查找 n - i 是否也为质数,同时满足时则符合要求。
需要注意的是,由于答案可能有多组,所求为字典序最小(即数字最小),所以我们最终输出的案例应当是符合要求时 i 最小的一组用例。
完整代码如下:
#include <bits/stdc++.h>
#define ms(a) memset(a,0,sizeof(a))
using namespace std;
int a[1000009];
int b[1000009];
int l=0;
void data()
{
ms(a),ms(b);
for(int i=1;i<=1e6;i++)
for(int j=i;j<=1e6;j+=i)
a[j]++;
for(int i=1;i<=1e6;i++)
if(a[i]==2){
b[l++]=i;
}
}
int main()
{
l=0;
data();
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int i=0;
int x,y;
while(i<l&&b[i]<=n)
{
x=b[i];
y=n-x;
if(a[y]==2)
break;
i++;
}
printf("%d %d\n",x,y);
}
return 0;
}