牛客挑战赛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;
}

原文地址:https://www.cnblogs.com/yinyuqin/p/15413380.html