【原创】Codeforces 45G Prime Problem

Codeforces 45G Prime Problem

题意翻译

将1到n分成若干组数,要求每组数的和均为质数,若存在一种分配方式,输出每个数所在的组的编号,有多组解输出任意一组解,若不存在,输出-1

感谢@he_____he 提供的翻译

题目描述

In Berland prime numbers are fashionable — the respectable citizens dwell only on the floors with numbers that are prime numbers. The numismatists value particularly high the coins with prime nominal values. All the prime days are announced holidays!

Yet even this is not enough to make the Berland people happy. On the main street of the capital stand n n n houses, numbered from 1 to n n n . The government decided to paint every house a color so that the sum of the numbers of the houses painted every color is a prime number.

However it turned out that not all the citizens approve of this decision — many of them protest because they don’t want many colored houses on the capital’s main street. That’s why it is decided to use the minimal possible number of colors. The houses don’t have to be painted consecutively, but every one of n n n houses should be painted some color. The one-colored houses should not stand consecutively, any way of painting is acceptable.

There are no more than 5 hours left before the start of painting, help the government find the way when the sum of house numbers for every color is a prime number and the number of used colors is minimal.

输入格式

The single input line contains an integer n n n ( 2 &lt; = n &lt; = 6000 2&lt;=n&lt;=6000 2<=n<=6000) — the number of houses on the main streets of the capital.

输出格式

Print the sequence of n n numbers, where the i − t h i -th ith number stands for the number of color for house number i i i . Number the colors consecutively starting from 1. Any painting order is allowed. If there are several solutions to that problem, print any of them. If there’s no such way of painting print the single number -1.

输入输出样例

输入 #1 复制

8

输出 #1 复制

1 2 2 1 1 1 1 2

分析

我起了,随意口胡出了正解却忽略了, W M D D N W^{D_N}_{M^D} WMDDN真就白给啊。

前置知识

  1. (强)哥德巴赫猜想: 任何任一大于2的偶数都可写成两个素数之和 → \to 至少 [ 1 , 6000 ∗ ( 6000 + 1 ) 2 ] [1,\frac{6000*(6000+1)}{2}] [1,26000(6000+1)]是成立的。
  2. (弱)哥德巴赫猜想: 任意一个>5的奇数都可写成三个素数之和 → \to 已被证明 (简易证明,在 [ 1 , 6000 ∗ ( 6000 + 1 ) 2 ] [1,\frac{6000*(6000+1)}{2}] [1,26000(6000+1)]内的奇数,可以拿一个3出来,然后使用强哥猜←我随意口胡出来的)

我们首先求出一个 S = 1 + 2 + ⋯ + n = Σ i = 1 n i = n ∗ ( n + 1 ) 2 S=1+2+\cdots+n=\Sigma^n_{i=1} i=\frac{n*(n+1)}{2} S=1+2++n=Σi=1ni=2n(n+1),然后

{ 所 有 数 都 在 一 个 集 合 , if S是质数 … … 1 ◯ 分 为 两 个 奇 质 数 的 和 , if S是偶数 … … 2 ◯ 要 么 分 为 2 和 一 个 奇 质 数 , 要 么 分 为 3 和 两个奇质数 一个偶数 , if S是奇合数 … … 3 ◯ \begin{cases} 所有数都在一个集合,&amp;\text{if S是质数} &amp;……\text{\textcircled 1} \\ 分为两个奇质数的和,&amp;\text{if S是偶数} &amp;……\text{\textcircled 2}\\ 要么分为2和一个奇质数,要么分为3和{\raisebox{0.75mm}{两个奇质数} \atop \raisebox{2.7mm}{一个偶数}},&amp;\text{if S是奇合数} &amp;……\text{\textcircled 3}\\ \end{cases} ,,23一个偶数两个奇质数,if S是质数if S是偶数if S是奇合数123

③的情况2,举一个 1 + 2 + 3 + 4 + 5 = 15 1+2+3+4+5=15 1+2+3+4+5=15的例子就看出来了。

首先我们是否能用 { 1 , 2 , ⋯ &ThinSpace; , n } \{1,2,\cdots,n\} {1,2,,n}来组合出这一个或两个奇质数?
正确性十分显然,对于①,略;对于②,显然, p 1 + p 2 = S = 1 + 2 + ⋯ + n p_1+p_2=S=1+2+\cdots+n p1+p2=S=1+2++n,显然只要存在两个质数之和为 S S S,就可以用 { 1 , 2 , ⋯ &ThinSpace; , n } \{1,2,\cdots,n\} {1,2,,n}组合出来;对于③也是同理显然。
(我还居然没有看出来)
那么怎么用 { 1 , 2 , ⋯ &ThinSpace; , n } \{1,2,\cdots,n\} {1,2,,n}来组合出这两个奇质数?
我们发现,我们总能找到 p 1 + p 2 = S    满 足    p 1 ≤ p 2   &amp; &amp;   p 1 &lt; = n p_1+p_2=S ~~满足~~ p_1\leq p_2 ~ \And\And ~p_1&lt;=n p1+p2=S    p1p2 && p1<=n,那么答案就是这两堆 { p 1 } , { 1 , 2 , ⋯ &ThinSpace; , p 1 − 1 , p 1 + 1 , ⋯ &ThinSpace; , n } \{p_1\},\{1,2,\cdots,p_1-1,p_1+1,\cdots,n\} {p1},{1,2,,p11,p1+1,,n}

为什么呢?
通过暴力枚举(跑了一上午)发现对于 n ≤ 40000000 , S = n ∗ ( n + 1 ) 2 n\leq 40000000,S=\frac{n*(n+1)}{2} n40000000S=2n(n+1)都满足,而且效率还很高。
(为了写暴力验证程序写着写着就把题解写出来了)

为什么呢?
为什么呢?
为什么呢?

有人说因为 n 2 &gt; S n^2&gt;S n2>S所以必然存在,但我不懂。
我太菜了。

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAXN=12030;
int n,ans[MAXN];

bool is_prime(int p)
{
	int sq=sqrt(p);
	for(int i=2;i<=sq;i++)
		if(p%i==0) return 0;
	return 1;
}

int main() 
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) ans[i]=1;
		
	int S=n*(n+1)/2;
	if(!is_prime(S))
	{
		if(S%2==0)
		{
			for(int i=2;i<=n;i++)
				if(is_prime(i) && is_prime(S-i))
				{
					ans[i]=2;
					break;
				}
		}
		else
		{
			if(is_prime(S-2)) ans[2]=2;
			else 
			{
				ans[3]=3;
				for(int i=2;i<=n;i++)
					if(is_prime(i) && is_prime(S-i-3))
					{
						ans[i]=2;
						break;
					}
			}
		}
	}
	for(int i=1;i<=n;i++) printf("%d%s",ans[i],i==n?"\n":" ");
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值