题意:给出一个数,把它分解成几个素数相加的形式,要求分解出的素数的数量最小。
这题分情况讨论就可以了,首先需要知道哥德巴赫猜想即一个大于4的偶数可以分解成两个素数和的形式。其次需要知道奇数加奇数等于偶数,奇数减奇数等于偶数。
那么首先判断n是否是素数,如果是直接输出n就可以。
接下来判断如果n是奇数,那么先判断n-2是否是素数,如果是的话那么最小数量的素数和即n-2 与 2,如果不是那么肯定能减一个奇素数数得到一个偶数再分解成两个素数。这个奇素数首选肯定是3,因为3最小适合绝大多数情况。
如果n是偶数,那么直接分解成两个素数即可。
分解偶数直接枚举素数暴力就可以了。这里数据弱了,n不大于maxn可行,不然还是得一个一个枚举。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<set> using namespace std; #define maxn 100010 bool isprime[maxn]; int prime[maxn],nprime; void getprime() { memset(isprime,1,sizeof(prime)); long long i,j; nprime=0; for(i=2; i<maxn; i++) if(isprime[i]) { prime[nprime++]=i; for(j=i*i; j<maxn; j+=i)isprime[j]=0; } } bool judgeprime(int n) { if(n<maxn)return isprime[n]; int l=(int)sqrt(n*1.0); for(int i=0; prime[i]<=l; i++) if(n%prime[i]==0)return 0; return 1; } void divideeven(int n,int &x,int &y) { for(int i=1; prime[i]<n; i++) if(judgeprime(n-prime[i])) { x=prime[i],y=n-x; return; } } int main() { int t,n,x,y; getprime(); scanf("%d",&t); while(t--) { scanf("%d",&n); if(judgeprime(n)) { printf("%d\n",n); continue; } if(n&1) { if(judgeprime(n-2))printf("2 %d\n",n-2); else divideeven(n-3,x,y),printf("3 %d %d\n",x,y); } else divideeven(n,x,y),printf("%d %d\n",x,y); } return 0; }