mathe
发表于 2008-4-16 17:45:20
下面程序在我的计算机上运行了将近一个小时,没有找到任何结果。
如果程序没有错误(很有可能哪里不小心弄错了一点),那么超完美的就是无解了。#include <stdio.h>
#define BUF_SIZE ((1<<20)>>5)
#define HALF_TABLE (1<<10)
#define GET_WORD(x) ((x)>>5)
#define GET_INDEX(x) ((x)&31)
#define SET_BIT(x)pbuf|=1<<GET_INDEX(x)
#define TEST_BIT(x) (pbuf&(1<<GET_INDEX(x)))
int pbuf;
#define IS_PRIME(x) (!TEST_BIT(x))
#define SET_NOT_PRIME(x) SET_BIT(x)
#define MCOUNT 68906
int p1;//用于保存所有6位素数(要求逆向读也是素数)
int p2;//用于保存所有可以用于4条边上的素数
int index1;///根据6位素数的最高位和最低位取值,分组
int index2;///根据最高位的值分组
int c1,c2;
int is_contain_zero(int x);
int last_column(int x);
int is_reverse_prime(int x);
int is_short_reverse(int x, int k);
int is_edge_prime(int x);
#define LOWER 100000
#define UPPER 999999
int cmp_p(const void *p, const void *q){
const int *cp=(const int *)p;
const int *cq=(const int *)q;
int sp=*cp%10;
int ep=*cp/LOWER;
int sq=*cq%10;
int eq=*cq/LOWER;
if(ep<eq)return -1;
if(ep>eq)return 1;
if(sp<sq)return -1;
if(sp>sq)return 1;
return *cp-*cq;
}
void init_prime()
{
int i,j,s,u;
SET_NOT_PRIME(0);
SET_NOT_PRIME(1);
for(i=2;i<HALF_TABLE;i++){
if(IS_PRIME(i)){
for(j=i*i;j<=UPPER;j+=i){
SET_NOT_PRIME(j);
}
}
}
s=1;u=10;
for(i=1;i<=5;i++){
for(j=s;j<u;j++){
if(IS_PRIME(j)&&!is_short_reverse(j,i)){
SET_NOT_PRIME(j);
}
}
s=u;u*=10;
}
c1=c2=0;
for(i=LOWER;i<=UPPER;i++){
if(IS_PRIME(i)&&is_reverse_prime(i)){
p1=i;
if(is_edge_prime(i)){
p2=i;
}
}else{
SET_NOT_PRIME(i);
}
}
qsort(p1,c1,sizeof(int),cmp_p);
for(i=0,j=1,index2=0;i<c2;i++){
if(p2>=(j+1)*LOWER){
index2=i;
j++;
}
while(p2>=(j+1)*LOWER){
index2=i;
j++;
}
}
for(;j<10;j++)index2=c2;
for(i=0,j=1,index1=0;i<c1;i++){
int high=j/10,lower=j%10;
int p=p1;
int ph=p/LOWER,pl=p%10;
if(ph!=high||pl!=lower){
int next_j=ph*10+pl;
for(;j<next_j;j++){
index1=i;
}
}
}
for(;j<100;j++)index1=c1;
fprintf(stderr,"c1=%d,c2=%d\n",c1,c2);
}
int is_short_reverse(int x, int k)
{
int i,y;
y=0;
for(i=0;i<k;i++){
y*=10;
y+=x%10;
x/=10;
}
return IS_PRIME(y);
}
int is_reverse_prime(int x)
{
int i,y;
y=0;
for(i=0;i<6;i++){
y*=10;
y+=x%10;
x/=10;
}
return IS_PRIME(y);
}
int is_contain_zero(int x)
{
int i;
for(i=0;i<6;i++){
if(x%10==0)return 1;
x/=10;
}
return 0;
}
int is_edge_prime(int x)
{
int last=x%10;
if(!IS_PRIME(last))
return 0;
if(!IS_PRIME(x/100000))
return 0;
if(!last_column(x))
return 0;
return !is_contain_zero(x);
}
int last_column(int x)
{
int valid={0,1,0,1,0,0,0,1,0,1};
int i;
for(i=0;i<6;i++){
int d=x%10;
if(!valid)return 0;
x/=10;
}
return 1;
}
char board;
void check_row()
{
int i,j,s;
for(i=1;i<6;i++){
int x=0;
for(j=0;j<6;j++){
x*=10;
x+=board;
}
if(!IS_PRIME(x))
return;
}
s=0;
for(i=0;i<6;i++){
s*=10;
s+=board;
}
if(!IS_PRIME(s))
return;
s=0;
for(i=0;i<6;i++){
s*=10;
s+=board;
}
if(!IS_PRIME(s))
return;
for(i=0;i<6;i++){///first check s+t=i
int sp=0;
for(j=0;j<=i;j++){
sp*=10;
sp+=board;
}
if(!IS_PRIME(sp))
return;
sp=0;
for(j=i;j<=5;j++){///check s+t = 5+i
sp*=10;
sp+=board;
}
if(!IS_PRIME(sp))
return;
sp=0;
for(j=0;j<=5-i;j++){///check s-t=i;
sp*=10;
sp+=board;
}
if(!IS_PRIME(sp))
return;
sp=0;
for(j=0;j<=5-i;j++){///Check s-t=-i;
sp*=10;
sp+=board;
}
if(!IS_PRIME(sp))
return;
}
for(i=0;i<6;i++){
for(j=0;j<6;j++){
printf("%d",board);
}
printf("\n");
}
printf("\n");
fflush(stdout);
}
void search()
{
int p,q;
int pp,qq,ss,tt;
int i,j;
for(pp=0;pp<c2;pp++){
int lead;
int s;
p=p2;
lead=p/LOWER;
s=p;
for(i=0;i<6;i++){
board=s%10;
s/=10;
}
for(qq=index2;qq<index2;qq++){
int j1,j2,j3,j4;
int h1,h2,h3,h4;
int sp;
q=p2;
s=q;
for(j=0;j<6;j++){
board=s%10;
s/=10;
}
sp=10*board+board;
if(!IS_PRIME(sp))
continue;
fprintf(stderr,"begin with edge <%d,%d,...>\n",p2,p2);
for(ss=index2-1];ss<index2];ss++){
s=p2;
for(i=0;i<6;i++){
board=s%10;
s/=10;
}
sp=10*board+board;
if(!IS_PRIME(sp))
continue;
for(tt=index2-1];tt<index2];tt++){
s=p2;
if(s%10!=board)
continue;
for(i=0;i<6;i++){
board=s%10;
s/=10;
}
sp =10*board+board;
if(!IS_PRIME(sp))
continue;
sp = 10*board+board;
if(!IS_PRIME(sp))
continue;
h1=board*10+board;
h2=board*10+board;
h3=board*10+board;
h4=board*10+board;
for(j1=index1;j1<index1;j1++){
s=p1;
for(j=0;j<5;j++){
board=s%10;
s/=10;
}
sp=board*100+board*10+board;
if(!IS_PRIME(sp))
continue;
sp=board*100+board*10+board;
if(!IS_PRIME(sp))
continue;
for(j2=index1;j2<index1;j2++){
s=p1;
for(j=0;j<5;j++){
board=s%10;
s/=10;
}
sp=board*1000+board*100+board*10+board;
if(!IS_PRIME(sp))
continue;
sp=board*1000+board*100+board*10+board;
if(!IS_PRIME(sp))
continue;
for(j3=index1;j3<index1;j3++){
s=p1;
for(j=0;j<5;j++){
board=s%10;
s/=10;
}
sp=board*10000+board*1000+board*100+board*10+board;
if(!IS_PRIME(sp))
continue;
sp=board*10000+board*1000+board*100+board*10+board;
if(!IS_PRIME(sp))
continue;
for(j4=index1;j4<index1;j4++){
s=p1;
for(j=0;j<5;j++){
board=s%10;
s/=10;
}
check_row();
}
}
}
}
}
}
}
}
}
int main()
{
init_prime();
search();
}
mathe
发表于 2008-4-16 17:49:33
如果将最外层的4个循环结果事先处理一下,去掉对称情况,应该可以提高将近8倍的速度
无心人
发表于 2008-4-16 17:54:31
那就去掉吧
要不来个低阶的看下?
mathe
发表于 2008-4-16 18:06:06
呵呵,最好两阶,这个显然有解:
$[(3,7),(7,3)]$
mathe
发表于 2008-4-16 18:06:40
哦,两阶都不行呀对角线不行 :'(
无心人
发表于 2008-4-16 20:23:44
:lol
那就满世界发帖子求一个超完美的
限定在16阶内
估计只要边界数字限定在1, 3, 7, 9就可以
葡萄糖
发表于 2019-3-17 22:27:07
找到一张图片
有趣的是,其定和为666;P
\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}