题目链接:
http://codeforces.com/problemset/problem/584/D
题目大意:
给一个奇数n,现在要将奇数拆分,可以拆成1个或者2个或者3个数的和,但是要保证拆出来的数是素数。现在要任意输出这样的一个答案。
思路:
先放结论:
在1~10^9范围内,任意两个素数的差不超过300。
对于一个数,我们可以分别考虑用1个或者2个或者3个数的情况。
1个:本身就是素数。
2个:因为给的是奇数,所以两个拆出来的数一定是一奇一偶,既是偶数又是素数的数只有2,所以我们只需判断n-2是否为素数即可。
3个:情况有两种:三个奇数,一奇二偶。
一奇二偶:二偶只能是2,2,所以判断n-4是否为奇数。
三个奇数:这就要用到前面的结论了。先找一个比n小的素数(尽量靠近n),因为在10^9范围内,两个素数差不超过300,所以我们就能很快的找到另一个素数。在做差以后得到x,剩下的两个数就在x里面暴力寻找即可。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<set>
#define mod 258280327
#define ll long long
using namespace std;
bool isok(int x)
{
if(x==2||x==3)return true;
for(int i=2;i<=sqrt(x);i++)
if(x%i==0)return false;
return true;
}
int main(){
int t,n;
int i,j,k;
scanf("%d",&n);
if(isok(n))printf("1\n%d\n",n);
else {
if(isok(n-2))printf("2\n2 %d\n",n-2);
else if(isok(n-4))printf("3\n2 2 %d\n",n-4);
else {
int x;
for(i=3;i<=300;i++)
{
if(isok(n-i)){
x=i;break;
}
}
if(isok(x))printf("2\n%d %d\n",x,n-x);
else {
// x=n-x;
for(i=2;i<=x;i++)
if(isok(i)&&isok(x-i)){
printf("3\n%d %d %d\n",i,x-i,n-x);
break;
}
}
}
}
return 0;
}