【GDOI2018模拟7.8】质数
2017-07-09 21:05
309 查看
Description
将1~n分成尽可能小的集合,使得每个集合的元素均为质数Input
一个数n(n<=6000)Output
第一行一个数m表示分成几块第二行n个1~m的数表示每个数分到哪一块
Sample Input
8Sample Output
21 2 2 1 1 1 1 2
Solution
这题很有趣我们知道有个哥德巴赫猜想:任意一个足够大的偶数可以分成两个质数的和
由于目前人类没有证明出它是错的,而且在6000以内通过枚举可以证明这是正确的
那么就直接用
分成几种情况考虑
记m=∑ni=1i
如果m为质数,显然分一块
如果m为偶数,可以枚举质数分成两块
如果m为奇数,并且m-2为质数,可以分成两块,分别是2和其它的数
否则分为三块,m-3会变成偶数,可以分成两块,第三块为3,可以证明这是正确的(至少在6000以内可以通过枚举证明)
Code
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define N 18003001 using namespace std; int ans,a ,p ,bz ,flag,n; int main() { scanf("%d",&n); if(n==1) { printf("-1\n"); return 0; } bz[1]=1; fo(i,2,N-1) { if(!bz[i]) p[++p[0]]=i; fo(j,1,p[0]) { if(i*p[j]>=N) break; bz[i*p[j]]=1; if(i%p[j]==0) break; } } int jy=(1+n)*n/2; if(bz[jy]==0) { printf("1\n"); fo(i,1,n) printf("1 "); } if(jy%2==0) { fo(i,1,p[0]) if(bz[jy-p[i]]==0) { int x=p[i]; fd(j,n,1) { if(j<=x) x-=j,a[j]=1; } printf("2\n"); fo(j,1,n) printf("%d ",a[j]==1?1:2); return 0; } } else { if(bz[jy-2]==0) { printf("2\n1 2 "); fo(i,3,n) printf("1 "); return 0; } else { fd(i,n,1) { if(bz[i]==0) { a[i]=3;jy-=i;break; } } fo(i,1,p[0]) if(bz[jy-p[i]]==0) { int x=p[i]; fd(j,n,1) if(a[j]==0) { if(j<=x) x-=j,a[j]=2; } printf("3\n"); fo(j,1,n) printf("%d\n ",a[j]>1?a[j]:1); return 0; } } } }
相关文章推荐
- 【GDOI2018模拟7.8】质数 乱搞+哥德巴赫猜想
- 质数,函数【GDOI2018模拟7.8】
- [JZOJ5250]【GDOI2018模拟8.11】质数
- 【jzoj5250】【GDOI2018模拟8.11】【质数】
- 【JZOJ 5250】【GDOI2018模拟8.11】质数
- 【GDOI2018模拟8.11】质数
- 【JZOJ5250】【GDOI2018模拟8.11】质数
- 【GDOI2018模拟8.11】质数
- 【JZOJ5250】【GDOI2018模拟】质数(数论)
- 【GDOI2018模拟7.8】矩阵
- 【JZOJ5220】【GDOI2018模拟7.10】C
- 【jzoj5220】【GDOI2018模拟7.10】【C】【动态规划】
- 【JZOJ 5220】【GDOI2018模拟7.10】C
- 【jzoj5223】【GDOI2018模拟7.12】【B】【矩阵乘法】
- 2018.01.27【GDOI2018】模拟C组
- 【jzoj5238】【GDOI2018模拟8.7】【的士碰撞】
- 【GDOI2018模拟8.12】求和
- 【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟9.21】数列
- JZOJ 5207【GDOI2018模拟7.7】暴力大神hxx