牛客挑战赛53 B.简单的序列(bitset,哥德巴赫猜想)
传送门
解题思路
和洛谷 P3674 很像。首先对于质数输出其本身。然后对于合数,根据哥德巴赫猜想,偶数一定可以由两个质数相加得到,而奇数则可以由两个或者三个质数得到。
但是三个数的和不好找,于是可以把奇数-1得到偶数进行求解。
然后就可以预处理1~1e7的质数,扔到bitset里,每次询问相当于询问是否有两个数相加的和为s。
总复杂度\(O(\frac{TS}{w})\)。
但评测机波动赛时两发没过赛后一发就过了就离大谱了。。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7;
int T,s,prime[maxn/10+5],cnt;
bitset<10000005> a,b,c;
bool vis[maxn+5];
int main(){
ios::sync_with_stdio(false);
a[1]=b[maxn-1]=1;
for(int i=2;i<=maxn;i++){
if(!vis[i]) prime[++cnt]=i;
for(int j=1;j<=cnt&&i*prime[j]<=maxn;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
for(int i=1;i<=cnt;i++) a[prime[i]]=b[maxn-prime[i]]=1;
cin>>T;
while(T--){
cin>>s;
if(vis[s]==0){
cout<<1<<endl<<s<<" = "<<s<<endl;
continue;
}
if(s==0){
cout<<1<<endl<<"0 = 0"<<endl;
continue;
}
c=b&(a<<(maxn-s));
if(c.any()){
int x=maxn-c._Find_first();
cout<<2<<endl<<x<<" + "<<s-x<<" = "<<s<<endl;
continue;
}else{
s--;
c=b&(a<<(maxn-s));
int x=maxn-c._Find_first();
cout<<3<<endl<<"1 + "<<x<<" + "<<s-x<<" = "<<s+1<<endl;
}
}
return 0;
}