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

[擂台] 素数幻方

[复制链接]
发表于 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-5-10 13:17 , Processed in 0.045144 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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