找回密码
 欢迎注册
楼主: 无心人

[擂台] 素数幻方

[复制链接]
发表于 2008-4-16 17:45:20 | 显示全部楼层
下面程序在我的计算机上运行了将近一个小时,没有找到任何结果。 如果程序没有错误(很有可能哪里不小心弄错了一点),那么超完美的就是无解了。
  1. #include <stdio.h>
  2. #define BUF_SIZE ((1<<20)>>5)
  3. #define HALF_TABLE (1<<10)
  4. #define GET_WORD(x) ((x)>>5)
  5. #define GET_INDEX(x) ((x)&31)
  6. #define SET_BIT(x) pbuf[GET_WORD(x)]|=1<<GET_INDEX(x)
  7. #define TEST_BIT(x) (pbuf[GET_WORD(x)]&(1<<GET_INDEX(x)))
  8. int pbuf[BUF_SIZE];
  9. #define IS_PRIME(x) (!TEST_BIT(x))
  10. #define SET_NOT_PRIME(x) SET_BIT(x)
  11. #define MCOUNT 68906
  12. int p1[MCOUNT];//用于保存所有6位素数(要求逆向读也是素数)
  13. int p2[MCOUNT];//用于保存所有可以用于4条边上的素数
  14. int index1[100];///根据6位素数的最高位和最低位取值,分组
  15. int index2[10];///根据最高位的值分组
  16. int c1,c2;
  17. int is_contain_zero(int x);
  18. int last_column(int x);
  19. int is_reverse_prime(int x);
  20. int is_short_reverse(int x, int k);
  21. int is_edge_prime(int x);
  22. #define LOWER 100000
  23. #define UPPER 999999
  24. int cmp_p(const void *p, const void *q){
  25. const int *cp=(const int *)p;
  26. const int *cq=(const int *)q;
  27. int sp=*cp%10;
  28. int ep=*cp/LOWER;
  29. int sq=*cq%10;
  30. int eq=*cq/LOWER;
  31. if(ep<eq)return -1;
  32. if(ep>eq)return 1;
  33. if(sp<sq)return -1;
  34. if(sp>sq)return 1;
  35. return *cp-*cq;
  36. }
  37. void init_prime()
  38. {
  39. int i,j,s,u;
  40. SET_NOT_PRIME(0);
  41. SET_NOT_PRIME(1);
  42. for(i=2;i<HALF_TABLE;i++){
  43. if(IS_PRIME(i)){
  44. for(j=i*i;j<=UPPER;j+=i){
  45. SET_NOT_PRIME(j);
  46. }
  47. }
  48. }
  49. s=1;u=10;
  50. for(i=1;i<=5;i++){
  51. for(j=s;j<u;j++){
  52. if(IS_PRIME(j)&&!is_short_reverse(j,i)){
  53. SET_NOT_PRIME(j);
  54. }
  55. }
  56. s=u;u*=10;
  57. }
  58. c1=c2=0;
  59. for(i=LOWER;i<=UPPER;i++){
  60. if(IS_PRIME(i)&&is_reverse_prime(i)){
  61. p1[c1++]=i;
  62. if(is_edge_prime(i)){
  63. p2[c2++]=i;
  64. }
  65. }else{
  66. SET_NOT_PRIME(i);
  67. }
  68. }
  69. qsort(p1,c1,sizeof(int),cmp_p);
  70. for(i=0,j=1,index2[0]=0;i<c2;i++){
  71. if(p2[i]>=(j+1)*LOWER){
  72. index2[j]=i;
  73. j++;
  74. }
  75. while(p2[i]>=(j+1)*LOWER){
  76. index2[j]=i;
  77. j++;
  78. }
  79. }
  80. for(;j<10;j++)index2[j]=c2;
  81. for(i=0,j=1,index1[0]=0;i<c1;i++){
  82. int high=j/10,lower=j%10;
  83. int p=p1[i];
  84. int ph=p/LOWER,pl=p%10;
  85. if(ph!=high||pl!=lower){
  86. int next_j=ph*10+pl;
  87. for(;j<next_j;j++){
  88. index1[j]=i;
  89. }
  90. }
  91. }
  92. for(;j<100;j++)index1[j]=c1;
  93. fprintf(stderr,"c1=%d,c2=%d\n",c1,c2);
  94. }
  95. int is_short_reverse(int x, int k)
  96. {
  97. int i,y;
  98. y=0;
  99. for(i=0;i<k;i++){
  100. y*=10;
  101. y+=x%10;
  102. x/=10;
  103. }
  104. return IS_PRIME(y);
  105. }
  106. int is_reverse_prime(int x)
  107. {
  108. int i,y;
  109. y=0;
  110. for(i=0;i<6;i++){
  111. y*=10;
  112. y+=x%10;
  113. x/=10;
  114. }
  115. return IS_PRIME(y);
  116. }
  117. int is_contain_zero(int x)
  118. {
  119. int i;
  120. for(i=0;i<6;i++){
  121. if(x%10==0)return 1;
  122. x/=10;
  123. }
  124. return 0;
  125. }
  126. int is_edge_prime(int x)
  127. {
  128. int last=x%10;
  129. if(!IS_PRIME(last))
  130. return 0;
  131. if(!IS_PRIME(x/100000))
  132. return 0;
  133. if(!last_column(x))
  134. return 0;
  135. return !is_contain_zero(x);
  136. }
  137. int last_column(int x)
  138. {
  139. int valid[10]={0,1,0,1,0,0,0,1,0,1};
  140. int i;
  141. for(i=0;i<6;i++){
  142. int d=x%10;
  143. if(!valid[d])return 0;
  144. x/=10;
  145. }
  146. return 1;
  147. }
  148. char board[6][6];
  149. void check_row()
  150. {
  151. int i,j,s;
  152. for(i=1;i<6;i++){
  153. int x=0;
  154. for(j=0;j<6;j++){
  155. x*=10;
  156. x+=board[i][5-j];
  157. }
  158. if(!IS_PRIME(x))
  159. return;
  160. }
  161. s=0;
  162. for(i=0;i<6;i++){
  163. s*=10;
  164. s+=board[i][i];
  165. }
  166. if(!IS_PRIME(s))
  167. return;
  168. s=0;
  169. for(i=0;i<6;i++){
  170. s*=10;
  171. s+=board[i][5-i];
  172. }
  173. if(!IS_PRIME(s))
  174. return;
  175. for(i=0;i<6;i++){///first check s+t=i
  176. int sp=0;
  177. for(j=0;j<=i;j++){
  178. sp*=10;
  179. sp+=board[j][i-j];
  180. }
  181. if(!IS_PRIME(sp))
  182. return;
  183. sp=0;
  184. for(j=i;j<=5;j++){///check s+t = 5+i
  185. sp*=10;
  186. sp+=board[j][5+i-j];
  187. }
  188. if(!IS_PRIME(sp))
  189. return;
  190. sp=0;
  191. for(j=0;j<=5-i;j++){///check s-t=i;
  192. sp*=10;
  193. sp+=board[i+j][j];
  194. }
  195. if(!IS_PRIME(sp))
  196. return;
  197. sp=0;
  198. for(j=0;j<=5-i;j++){///Check s-t=-i;
  199. sp*=10;
  200. sp+=board[j][i+j];
  201. }
  202. if(!IS_PRIME(sp))
  203. return;
  204. }
  205. for(i=0;i<6;i++){
  206. for(j=0;j<6;j++){
  207. printf("%d",board[i][j]);
  208. }
  209. printf("\n");
  210. }
  211. printf("\n");
  212. fflush(stdout);
  213. }
  214. void search()
  215. {
  216. int p,q;
  217. int pp,qq,ss,tt;
  218. int i,j;
  219. for(pp=0;pp<c2;pp++){
  220. int lead;
  221. int s;
  222. p=p2[pp];
  223. lead=p/LOWER;
  224. s=p;
  225. for(i=0;i<6;i++){
  226. board[0][5-i]=s%10;
  227. s/=10;
  228. }
  229. for(qq=index2[lead-1];qq<index2[lead];qq++){
  230. int j1,j2,j3,j4;
  231. int h1,h2,h3,h4;
  232. int sp;
  233. q=p2[qq];
  234. s=q;
  235. for(j=0;j<6;j++){
  236. board[5-j][0]=s%10;
  237. s/=10;
  238. }
  239. sp=10*board[1][0]+board[0][1];
  240. if(!IS_PRIME(sp))
  241. continue;
  242. fprintf(stderr,"begin with edge <%d,%d,...>\n",p2[pp],p2[qq]);
  243. for(ss=index2[board[0][5]-1];ss<index2[board[0][5]];ss++){
  244. s=p2[ss];
  245. for(i=0;i<6;i++){
  246. board[5-i][5]=s%10;
  247. s/=10;
  248. }
  249. sp=10*board[0][4]+board[1][5];
  250. if(!IS_PRIME(sp))
  251. continue;
  252. for(tt=index2[board[5][0]-1];tt<index2[board[5][0]];tt++){
  253. s=p2[tt];
  254. if(s%10!=board[5][5])
  255. continue;
  256. for(i=0;i<6;i++){
  257. board[5][5-i]=s%10;
  258. s/=10;
  259. }
  260. sp =10*board[4][0]+board[5][1];
  261. if(!IS_PRIME(sp))
  262. continue;
  263. sp = 10*board[4][5]+board[5][4];
  264. if(!IS_PRIME(sp))
  265. continue;
  266. h1=board[0][1]*10+board[5][1];
  267. h2=board[0][2]*10+board[5][2];
  268. h3=board[0][3]*10+board[5][3];
  269. h4=board[0][4]*10+board[5][4];
  270. for(j1=index1[h1-1];j1<index1[h1];j1++){
  271. s=p1[j1];
  272. for(j=0;j<5;j++){
  273. board[5-j][1]=s%10;
  274. s/=10;
  275. }
  276. sp=board[2][0]*100+board[1][1]*10+board[0][2];
  277. if(!IS_PRIME(sp))
  278. continue;
  279. sp=board[3][0]*100+board[4][1]*10+board[5][2];
  280. if(!IS_PRIME(sp))
  281. continue;
  282. for(j2=index1[h2-1];j2<index1[h2];j2++){
  283. s=p1[j2];
  284. for(j=0;j<5;j++){
  285. board[5-j][2]=s%10;
  286. s/=10;
  287. }
  288. sp=board[3][0]*1000+board[2][1]*100+board[1][2]*10+board[0][3];
  289. if(!IS_PRIME(sp))
  290. continue;
  291. sp=board[2][0]*1000+board[3][1]*100+board[4][2]*10+board[5][3];
  292. if(!IS_PRIME(sp))
  293. continue;
  294. for(j3=index1[h3-1];j3<index1[h3];j3++){
  295. s=p1[j3];
  296. for(j=0;j<5;j++){
  297. board[5-j][3]=s%10;
  298. s/=10;
  299. }
  300. sp=board[4][0]*10000+board[3][1]*1000+board[2][2]*100+board[1][3]*10+board[0][4];
  301. if(!IS_PRIME(sp))
  302. continue;
  303. sp=board[1][0]*10000+board[2][1]*1000+board[3][2]*100+board[4][3]*10+board[5][4];
  304. if(!IS_PRIME(sp))
  305. continue;
  306. for(j4=index1[h4-1];j4<index1[h4];j4++){
  307. s=p1[j4];
  308. for(j=0;j<5;j++){
  309. board[5-j][4]=s%10;
  310. s/=10;
  311. }
  312. check_row();
  313. }
  314. }
  315. }
  316. }
  317. }
  318. }
  319. }
  320. }
  321. }
  322. int main()
  323. {
  324. init_prime();
  325. search();
  326. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 17:49:33 | 显示全部楼层
如果将最外层的4个循环结果事先处理一下,去掉对称情况,应该可以提高将近8倍的速度
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 17:54:31 | 显示全部楼层
那就去掉吧 要不来个低阶的看下?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 18:06:06 | 显示全部楼层
呵呵,最好两阶,这个显然有解: $[(3,7),(7,3)]$
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 18:06:40 | 显示全部楼层
哦,两阶都不行呀对角线不行
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 20:23:44 | 显示全部楼层
那就满世界发帖子求一个超完美的 限定在16阶内 估计只要边界数字限定在1, 3, 7, 9就可以
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2019-3-17 22:27:07 | 显示全部楼层
找到一张图片
有趣的是,其定和为666
\begin{array}{|r|r|r|r|}  
\hline 3 & 107 & 5 & 131 &109 &311 \\
\hline 7 & 331 & 193 & 11 &83 &41 \\  
\hline 103 & 53 & 71 & 89 &151 &199 \\  
\hline 113 & 61 & 97 & 197 &167 &31 \\
\hline 367 & 13 & 173 & 59 &17 &37 \\  
\hline 73 & 101 & 127 & 179 &139 &47 \\
\hline \end{array}
ePrime.jpg
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 20:40 , Processed in 0.030698 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表