IOI'94
In the square below, each row, each column and the two diagonals can be read as a five digit prime number. The rows are read from left to right. The columns are read from top to bottom. Both diagonals are read from left to right.
+---+---+---+---+---+ | 1 | 1 | 3 | 5 | 1 | +---+---+---+---+---+ | 3 | 3 | 2 | 0 | 3 | +---+---+---+---+---+ | 3 | 0 | 3 | 2 | 3 | +---+---+---+---+---+ | 1 | 4 | 0 | 3 | 3 | +---+---+---+---+---+ | 3 | 3 | 3 | 1 | 1 | +---+---+---+---+---+
- The prime numbers' digits must sum to the same number.
- The digit in the top left-hand corner of the square is pre-determined (1 in the example).
- A prime number may be used more than once in the same square.
- If there are several solutions, all must be presented (sorted in numerical order as if the 25 digits were all one long number).
- A five digit prime number cannot begin with a zero (e.g., 00003 is NOT a five digit prime number).
PROGRAM NAME: prime3
INPUT FORMAT
A single line with two space-separated integers: the sum of the digits and the digit in the upper left hand corner of the square.
SAMPLE INPUT (file prime3.in)
11 1
OUTPUT FORMAT
Five lines of five characters each for each solution found, where each line in turn consists of a five digit prime number. Print a blank line between solutions. If there are no prime squares for the input data, output a single line containing "NONE".
SAMPLE OUTPUT (file prime3.out)
The above example has 3 solutions.
11351 14033 30323 53201 13313 11351 33203 30323 14033 33311 13313 13043 32303 50231 13331
解题思路:
从昨天就在做这道题,题目很简单,做法也很明显(当然可以有多种搜索策略),但是优化却很重要。
第一次写,直接暴力,9重循环,也没预处理数组直接在里面%10...0/10...0这样算,结果超时。
优化了一下,先把素数表打好,压线1.9XX秒过。
不爽,想优化一个高效的出来,于是决定代码全推了重写,今天出去玩了一天回来才算是有时间完成这个程序。
写这么狗血的代码,这种orz的感觉只有自己体验过的才能懂得。。。
策略:
尽量让大支在外重循环被剪掉:因为左上角的数字是固定的,这是比较大的一个限制,所以先穷举斜角、第一行、第一列三个素数。然后观察,发现这时另一个斜角的限制最大(3个数已经被确定),枚举它。接着是第二行、第二列,他们也都是3个数字的限制。接着是第三列(或第三行),第三列填上一个固定的值之后,其余空格都可以通过“各位数字和固定”这个条件推算出来。推算玩验证一下就ok了。
输出的时候再排下序。
PS:筛法素数表
很多人都知道这个方法,但是也有很多人并不能写出最出色的筛法——他们的算法中往往有很多重复。
这个我个人总结的几个要点:
1、筛法通过在当前数字表中去掉各个已知素数的倍数(2倍及2倍以上)来得到最终的素数表
2、设置一个上限size
3、初始条件,我们已知0和1不是素数,2是素数
4、每次去除完素数x的倍数,那么区间0 ~ (x + 1) ^ 2 - 1剩下的数都是素数
orz的代码: