1 import java.io.*;
2 import java.util.*;
3 /*
4 ID: yanglei4
5 LANG: JAVA
6 TASK:prime3
7 */
8 public class prime3{
9 static boolean[] prime = new boolean[100001];
10 static int[] digit = new int[100001];
11
12 public static void main(String[] args) throws IOException {
13 BufferedReader fin = new BufferedReader(new FileReader("prime3.in"));
14 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("prime3.out")));
15 StringTokenizer st = new StringTokenizer(fin.readLine());
16 int sum = Integer.parseInt(st.nextToken());
17 int upperleft = Integer.parseInt(st.nextToken());
18 int totalcount = 0;
19 ArrayList<String> result = new ArrayList<String>();
20
21 if (sum % 3 == 0) {
22 out.println("NONE");
23 }
24 else {
25
26
27 //Find the primes first
28 Arrays.fill(prime, true);
29 for (int i = 0; i < 100000; i++)
30 if (i % 2 == 0)
31 prime[i] = false;
32 prime[1] = false;
33 prime[2] = true;
34
35 for(int i = 3; i <= 1000; i += 2 )
36 if(prime[i])
37 for(int j = i + i; j <= 100000; j += i ) prime[j] = false;
38
39 //count the digit
40 for (int i = 10001; i <= 99997; i++)
41 if (prime[i]) {
42 int temp = i;
43 int tempsum = 0;
44 while (temp != 0) {
45 tempsum += temp % 10;
46 temp /= 10;
47 }
48 digit[i] = tempsum;
49 }
50
51 int[] numbers = new int[100000];
52 int count = 0;
53 for (int i = 10001; i <= 99997; i++) {
54 if (prime[i] && digit[i] == sum)
55 numbers[count++] = i;
56 }
57
58 int[] line5 = new int[100000];
59 int countline5 = 0;
60 for (int i = 0; i < count; i++) {
61 int temp = numbers[i];
62 boolean flag = true;
63 while (temp != 0) {
64 int dit = temp % 10;
65 if (dit == 0 || dit == 2 || dit == 4 || dit ==5 || dit == 6 || dit == 8) {
66 flag = false;
67 break;
68 }
69 temp /= 10;
70 }
71 if (flag) line5[countline5++] = numbers[i];
72 }
73 // for (int i = 0; i < countline5; i++) System.out.println("* " + line5[i]);
74
75 int[] line1 = new int[100000];
76 int countline1 = 0;
77 for (int i = 0; i < count; i++) {
78 int firstdit = numbers[i] / 10000;
79 int seconddit = numbers[i] / 1000 % 10;
80 int thirddit = numbers[i] / 100 % 10;
81 int fourthdit = numbers[i] / 10 % 10;
82 if (firstdit == upperleft && seconddit != 0 && thirddit != 0 && fourthdit != 0)
83 line1[countline1++] = numbers[i];
84 }
85
86 boolean[][] firstfifth = new boolean[10][10];
87 boolean[][] secondfifth = new boolean[10][10];
88 boolean[][] thirdfifth = new boolean[10][10];
89 boolean[][] fourthfifth = new boolean[10][10];
90 boolean[][][] secondfourthfifth = new boolean[10][10][10];
91 boolean[][][][] firstsecondfourthfifth = new boolean[10][10][10][10];
92
93 for (int i = 0; i < count; i++)
94 {
95 int firstdit = numbers[i] / 10000;
96 int seconddit = numbers[i] / 1000 % 10;
97 int thirddit = numbers[i] / 100 % 10;
98 int fourthdit = numbers[i] / 10 % 10;
99 int fifthdit = numbers[i] % 10;
100 firstfifth[firstdit][fifthdit] = true;
101 secondfifth[seconddit][fifthdit] = true;
102 thirdfifth[thirddit][fifthdit] = true;
103 fourthfifth[fourthdit][fifthdit] = true;
104 secondfourthfifth[seconddit][fourthdit][fifthdit] = true;
105 firstsecondfourthfifth[firstdit][seconddit][fourthdit][fifthdit] = true;
106 }
107
108 //Start
109 int[][] map = new int[5][5];
110 map[0][0] = upperleft;
111
112 int temp = 0;
113 //row 5
114 for (int a = 0; a < countline5; a++) {
115 temp = line5[a];
116 for (int k = 4; k >= 0; k--) {
117 map[4][k] = temp % 10;
118 temp /= 10;
119 }
120
121 //column 5
122 for (int b = 0; b < countline5; b++)
123 if (map[4][4] == line5[b] % 10) {
124 temp = line5[b];
125 for (int k = 4; k >= 0; k--) {
126 map[k][4] = temp % 10;
127 temp /= 10;
128 }
129
130
131 //main dig
132 for (int c = 0; c < count; c++)
133 if (map[4][0] == numbers[c] / 10000 && map[0][4] == numbers[c] % 10) {
134
135 int seconddit = numbers[c] / 1000 % 10;
136 int thirddit = numbers[c] / 100 % 10;
137 int fourthdit = numbers[c] / 10 % 10;
138 if (secondfifth[seconddit][map[3][4]] == true &&
139 fourthfifth[seconddit][map[4][1]] == true &&
140 thirdfifth[thirddit][map[2][4]] == true &&
141 thirdfifth[thirddit][map[4][2]] == true &&
142 fourthfifth[fourthdit][map[1][4]] == true &&
143 secondfifth[fourthdit][map[4][3]] == true) {
144 map[3][1] = seconddit;
145 map[2][2] = thirddit;
146 map[1][3] = fourthdit;
147
148
149 //second dig
150 for (int d = 0; d < count; d++)
151 if (numbers[d] / 10000 == upperleft && numbers[d] % 10 == map[4][4] && numbers[d] / 100 % 10 == map[2][2]) {
152
153 seconddit = numbers[d] / 1000 % 10;
154 fourthdit = numbers[d] / 10 % 10;
155 if (secondfourthfifth[seconddit][map[3][1]][map[4][1]] == true &&
156 secondfourthfifth[seconddit][map[1][3]][map[1][4]] == true &&
157 secondfourthfifth[map[3][1]][fourthdit][map[3][4]] == true &&
158 secondfourthfifth[map[1][3]][fourthdit][map[4][3]] == true) {
159 map[1][1] = seconddit;
160 map[3][3] = fourthdit;
161
162 //first row
163 for (int e = 0; e < countline1; e++)
164 if (line1[e] % 10 == map[0][4]) {
165 seconddit = line1[e] / 1000 % 10;
166 thirddit = line1[e] / 100 % 10;
167 fourthdit = line1[e] / 10 % 10;
168 if (firstsecondfourthfifth[seconddit][map[1][1]][map[3][1]][map[4][1]] == false ||
169 firstsecondfourthfifth[fourthdit][map[1][3]][map[3][3]][map[4][3]] == false)
170 continue;
171
172 map[0][1] = seconddit;
173 map[0][2] = thirddit;
174 map[0][3] = fourthdit;
175
176 //first column
177 for (int f = 0; f < countline1; f++)
178 if (line1[f] % 10 == map[4][0]) {
179 seconddit = line1[f] / 1000 % 10;
180 thirddit = line1[f] / 100 % 10;
181 fourthdit = line1[f] / 10 % 10;
182 if (firstsecondfourthfifth[seconddit][map[1][1]][map[1][3]][map[1][4]] == false ||
183 firstsecondfourthfifth[fourthdit][map[3][1]][map[3][3]][map[3][4]] == false)
184 continue;
185 map[1][0] = seconddit;
186 map[2][0] = thirddit;
187 map[3][0] = fourthdit;
188
189 //left four digit
190 map[1][2] = sum - map[1][0] - map[1][1] - map[1][3] - map[1][4];
191 map[3][2] = sum - map[3][0] - map[3][1] - map[3][3] - map[3][4];
192 map[2][1] = sum - map[0][1] - map[1][1] - map[3][1] - map[4][1];
193 map[2][3] = sum - map[0][3] - map[1][3] - map[3][3] - map[4][3];
194
195 //check
196 if (map[1][2] < 0 || map[3][2] < 0 || map[2][1] < 0 || map[2][3] < 0) continue;
197 if (map[1][2] > 9 || map[3][2] > 9 || map[2][1] > 9 || map[2][3] > 9) continue;
198
199 int tempsum = 0;
200
201 for (int k = 0; k < 5; k++) tempsum += map[2][k];
202 if (tempsum != sum) continue;
203
204 tempsum = 0;
205 for (int k = 0; k < 5; k++) tempsum += map[k][2];
206 if (tempsum != sum) continue;
207
208
209 tempsum = 0;
210 //row 2
211 for (int k = 0; k < 5; k++) tempsum = tempsum * 10 + map[1][k];
212 if (tempsum <= 99999 && !prime[tempsum]) continue;
213
214 //row 3
215 tempsum = 0;
216 for (int k = 0; k < 5; k++) tempsum = tempsum * 10 + map[2][k];
217 if (tempsum <= 99999 && !prime[tempsum]) continue;
218
219 //row 4
220 tempsum = 0;
221 for (int k = 0; k < 5; k++) tempsum = tempsum * 10 + map[3][k];
222 if (tempsum <= 99999 && !prime[tempsum]) continue;
223
224 //column 2
225 tempsum = 0;
226 for (int k = 0; k < 5; k++) tempsum = tempsum * 10 + map[k][1];
227 if (tempsum <= 99999 && !prime[tempsum]) continue;
228
229 //column 3
230 tempsum = 0;
231 for (int k = 0; k < 5; k++) tempsum = tempsum * 10 + map[k][2];
232 if (tempsum <= 99999 && !prime[tempsum]) continue;
233
234 //column 4
235 tempsum = 0;
236 for (int k = 0; k < 5; k++) tempsum = tempsum * 10 + map[k][3];
237 if (tempsum <= 99999 && !prime[tempsum]) continue;
238
239 totalcount++;
240 StringBuffer sb = new StringBuffer();
241 for (int x = 0; x < 5; x++)
242 for (int y = 0; y < 5; y++)
243 sb.append(map[x][y]);
244
245 result.add(sb.toString());
246 }
247 }
248 }
249 }
250
251 }
252 }
253 }
254 }
255
256 }
257
258 if (totalcount > 0) {
259 Collections.sort(result);
260 int tc = 0;
261 for (String x : result) {
262 if (tc != 0)
263 out.println();
264 for (int i = 0; i < 5; i++) {
265 for (int j = 0; j < 5; j++)
266 out.print(x.charAt(i * 5 + j));
267 out.println();
268 }
269 tc++;
270 }
271
272 }
273 else
274 out.println("NONE");
275 out.close();
276 System.exit(0);
277 }
278 }
279
太爽了,这道题目居然用自己的算法过了,真不容易啊,将近300行的代码
大致说一下我怎么做的吧。
首先,我把0~99999所有的素数全部筛选了出来,用筛选法,应该很快就可以完成。
然后,我把这些素数中,数字和等于um的全部挑选出来,放在numbers里面
因为每行每列的数只有可能是这些number中的一个
我不知道这样做是不是能提前把搜索的范围减小,但是肯定的事这样做能过。
这样之后就是确定搜素顺序,我参考了NOCOW上面的顺序,先第五行,第五列,然后对角线,然后第一行第一列,最后把剩下的四个数用加法算出来。
在这此前,我做了进一步的预处理
首先,第五行(列)中的每个数字都不能是0 2 4 5 6 8,否则的话,该列(行)必然不是素数。我把这些数字预处理出来,放在line5里面
这一步应该能大大减小搜索范围。
然后是对角线,因为对角线的两个端点其实都已经确定了,所以只需要看中间的3个数
比如主对角线,因为左下和右上的数已经填好了,我们就需要从numbers中找出来符合的数填进去。
在这过程中,还可以加上一步剪枝
0 0 0 0 1
0 0 0 c 2
0 0 b 0 3
0 a 0 0 4
1 2 3 4 5
注意你在填a,b,c的时候,其实你已经影响了第二行第二列,第三行第三列,第四行第四列了。
当你在填a的时候,第二列的后两个数就确定了,第四列的2,5数就确定了。
这样的话我们可以去numbers中查找,如果不存在后两个数是a2,和第2,4位是a..4的数,那么就直接continue
至于怎么查找,我们可以在之前预处理,设一个数组secondfifth[][],fourthfifth[][]
然后把所有numbers遍历一遍,把这两个数组初始化,这两个数组第[i][j]表示存在一个素数,第2,5(4,5)位是i,j
同理,副对角线也是可以这样剪枝的。
然后就是第一行,第一列了,以第一行为例。
第一行也是第一个和第五个已经确定了,只需要中间三个就行,我开始没有做剪枝,就是直接把所有的全弄上去了。
结果居然没有过,后来又加了一个剪枝
1 2 3 4 1
0 2 0 4 2
0 0 3 0 3
0 2 0 4 4
1 2 3 4 5
看第二列第四列,跟前面的情况相同,第1,2,4,5位已经确定,于是可以先预处理一个数组,把numbers里面的
每一个的1,2,4,5位提出来,然后把相应的数组位设成是true
第一列也可以这样做。
这样矩阵中就剩下4个数了,[2,3],[3,2],[3,4],[4,3],这样的话,可以用第二列,第四列,第二行,第四行算出来。
然后就是进行最后的check
1、算出来的每个数必须要大于等于0,小于10
2、第2~4行,第2~4列必须是素数
做过这两个之后,剩下的就是满足条件的了。
然后把这个数组存储到一个String里面,等所有的全选好了,再用sort一下