B: Prime Split
题解:
1、先判断两个素数w[i]、w[j]的和是否大于n-2,若小于则说明数字n不可能由三个素数组成(2是最小的素数)
2、再判断n-w[i]-w[j]是否是素数
3、保证w[i]、w[j]、n-w[i]-w[j]是递增的,避免重复计数
//注意laz[]要和线段树数组开一样大小 #include<iostream> #include<algorithm> #include<vector> #include<math.h> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn = 40005; int prim[maxn], w[maxn], cnt = 0;//prim[i]起标记作用,prim[i]==0表示i是质数,注意这里把1也标记成了质数 int x[maxn];//x[i]表示偶数是i的符合条件的两个质数是x[i]和i-x[i]; void init() { memset(prim, false, sizeof(prim)); prim[1]=1;//1不是素数 for(int i = 2; i < maxn; i++) { if(prim[i]) //判断i是否为偶数 continue; w[cnt++] = i;//w存质数 for(int j = i << 1; j < maxn; j+=i)//把所有质数的倍数标记 prim[j] = true; } } int main() { int t,n; cin>>t; init(); while(t--) { cin>>n; int ans=0; for(int i=0;i<cnt;i++) { for(int j=i;j<cnt;j++) { int k=w[i]+w[j]; if(k>n-2)//2是最小的素数,这里判断不可能由三个素数组成的情况 break; int temp=n-k; if(temp<w[j])//保证三个素数w[i],w[j],temp是递增的,避免下面重复计数 continue; if(prim[temp]==0) ans++; } } cout<<ans<<endl; } return 0; }