CF45G Prime Problem(构造)

\(1\)\(n\) 分成若干组数,要求每组数的和均为质数,在这个前提下让组数尽量少,若存在一种分配方式,输出每个数所在的组的编号,有多组解输出任意一组解,若不存在,输出 \(−1\)

\(m\)\(1\)\(n\) 的和(等差数列求和),进行分类讨论:

  • \(m\) 是质数,所有的数分同一组;
  • \(m\) 是偶合数,根据哥德巴赫猜想的推论,一定能分解为两个质数相加,\(O(m)\) 找到哪个数要分进第 \(2\) 组即可;
  • \(m\) 是奇合数,若 \(m-2\) 是质数,则可分为两组,否则减去 \(3\),转化为偶合数再分解。

做完上面 \(3\) 步,就知道 \(-1\) 纯属诈骗,根本不可能存在。

时间复杂度 \(O(m)\),但 \(m\)\(n^2\) 量级。

做的时候不知道哥德巴赫猜想,直接 gg,打完暴力走人。

下面是 AC 代码:

#include<bits/stdc++.h>
int prime[10000000],a[6001];
bool vis[36000000];
int main(){
	int n=36000000,m=0,k;
	for(int i=2;i<=n;++i){
		if(!vis[i]) prime[++m]=i;
		for(int j=1,v;j<=m;++j){
			if((v=i*prime[j])>n) break;
			vis[v]=true;
			if(!(i%prime[j])) break;
		}
	}
	scanf("%d",&n),k=n*(n+1)>>1;
	if(vis[k]){
		bool flag=false;
		if(k&1){
			if(!vis[k-2]) a[2]=2,flag=true;
			else a[3]=3,k-=3;
		}
		if(!flag) for(int i=3;i<=k;++i) 
			if(!vis[i]&&!vis[k-i]){
				for(int j=n;j;--j) 
					if(i>=j) a[j]=2,i-=j;
				break;
			}		
	}
	for(int i=1;i<=n;++i)
		printf("%d ",std::max(a[i],1));
	return 0;
}

THE END

posted @ 2021-08-25 22:57  q0000000  阅读(47)  评论(0编辑  收藏  举报