这道题的原题大概找得到,自己去找吧.
题目大意就是让我们找到一个5*5矩阵,满足每一行从左往右,每一列从上到下,以及两条对角线从左往右的5位数都是素数且每一位数字加起来的和为sum,给定了矩阵的第一行第一列.
我一开始写了个暴力,结果样例都没跑过...
于是之后才知道应该是这样做的.
先预处理出一张素数表:
class prime{ public: int b[100000]; inline void start(int sum){ for (int i=1;i<100000;i++) b[i]=1; for (int i=1;i<10000;i++) b[i]=0; for (int i1=1;i1<=9;i1++) for (int i2=0;i2<=9;i2++) for (int i3=0;i3<=9;i3++) for (int i4=0;i4<=9;i4++) for (int i5=0;i5<=9;i5++){ int num=i1+i2+i3+i4+i5; if (num!=sum) { b[i1*10000+i2*1000+i3*100+i4*10+i5]=false; continue; } num=i1*10000+i2*1000+i3*100+i4*10+i5; for (int i=2;i<=sqrt(num+1);i++) if (num%i==0) { b[num]=false; break; } } } inline bool prim(int i1,int i2,int i3,int i4,int i5){ return b[i1*10000+i2*1000+i3*100+i4*10+i5]; } }p; //建立素数表p
先填掉\这条对角线三个数字,然后还有一个就推出来(黑色表示枚举的,红色表示已知或推出来的):
这一段代码如下:
inline void f3(){ for (int i=0;i<=9;i++){ e[top].c[3][3]=i; int num=sum-e[top].c[1][1]-e[top].c[3][3]-e[top].c[4][4]-e[top].c[5][5]; e[top].c[2][2]=num; if (num>9||num<0) continue; if (p.prim(e[top].c[1][1],e[top].c[2][2],e[top].c[3][3],e[top].c[4][4],e[top].c[5][5])) f4(); } } inline void f2(){ for (int i=0;i<=9;i++){ e[top].c[4][4]=i; f3(); } } inline void f1(){ e[++top].c[1][1]=fir; for (int i=0;i<=9;i++){ e[top].c[5][5]=i; f2(); } }
然后再填第一列的数,填三个:
代码如下:
inline void f6(){ for (int i=1;i<=9;i++){ e[top].c[3][1]=i; int num=sum-e[top].c[1][1]-e[top].c[3][1]-e[top].c[4][1]-e[top].c[5][1]; e[top].c[2][1]=num; if (num<0||num>9) continue; if (p.prim(e[top].c[1][1],e[top].c[2][1],e[top].c[3][1],e[top].c[4][1],e[top].c[5][1])) f7(); } } inline void f5(){ for (int i=1;i<=9;i++){ e[top].c[4][1]=i; f6(); } } inline void f4(){ for (int i=1;i<=9;i++){ e[top].c[5][1]=i; f5(); } }
之后继续填第2行填两个数:
代码如下:
inline void f8(){ for (int i=0;i<=9;i++){ e[top].c[2][5]=i; int num=sum-e[top].c[2][1]-e[top].c[2][2]-e[top].c[2][4]-e[top].c[2][5]; e[top].c[2][3]=num; if (num>9||num<0) continue; if (p.prim(e[top].c[2][1],e[top].c[2][2],e[top].c[2][3],e[top].c[2][4],e[top].c[2][5])) f9(); } } inline void f7(){ for (int i=0;i<=9;i++){ e[top].c[2][4]=i; f8(); } }
填/对角线一个数:
代码如下:
inline void f9(){ for (int i=0;i<=9;i++){ e[top].c[1][5]=i; int num=sum-e[top].c[1][5]-e[top].c[2][4]-e[top].c[3][3]-e[top].c[5][1]; e[top].c[4][2]=num; if (num<0||num>9) continue; if (p.prim(e[top].c[5][1],e[top].c[4][2],e[top].c[3][3],e[top].c[2][4],e[top].c[1][5])) f10(); } }
之后填第3行:
代码如下:
inline void f11(){ for (int i=0;i<=9;i++){ e[top].c[3][5]=i; int num=sum-e[top].c[3][1]-e[top].c[3][3]-e[top].c[3][4]-e[top].c[3][5]; e[top].c[3][2]=num; if (num<0||num>9) continue; if (!p.prim(e[top].c[3][1],e[top].c[3][2],e[top].c[3][3],e[top].c[3][4],e[top].c[3][5])) continue; e[top].c[4][5]=num=sum-e[top].c[1][5]-e[top].c[2][5]-e[top].c[3][5]-e[top].c[5][5]; if (num<0||num>9) continue; if (!p.prim(e[top].c[1][5],e[top].c[2][5],e[top].c[3][5],num,e[top].c[5][5])) continue; e[top].c[4][3]=num=sum-e[top].c[4][1]-e[top].c[4][2]-e[top].c[4][4]-e[top].c[4][5]; if (num<0||num>9) continue; if (p.prim(e[top].c[4][1],e[top].c[4][2],e[top].c[4][3],e[top].c[4][4],e[top].c[4][5])) f12(); } } inline void f10(){ for (int i=0;i<=9;i++){ e[top].c[3][4]=i; f11(); } }
之后再填掉一个:
代码如下:
inline void f12(){ for (int i=0;i<=9;i++){ e[top].c[5][2]=i; int num=sum-e[top].c[2][2]-e[top].c[3][2]-e[top].c[4][2]-e[top].c[5][2]; e[top].c[1][2]=num; if (num<0||num>9) continue; if (p.prim(e[top].c[1][2],e[top].c[2][2],e[top].c[3][2],e[top].c[4][2],e[top].c[5][2])) f13(); } }
灭绝人性的最后一个填了:
代码如下:
inline void f13(){ for (int i=0;i<=9;i++){ e[top].c[5][3]=i; int num=sum-e[top].c[2][3]-e[top].c[3][3]-e[top].c[4][3]-e[top].c[5][3]; e[top].c[1][3]=num; if (num<0||num>9) continue; if (!p.prim(num,e[top].c[2][3],e[top].c[3][3],e[top].c[4][3],e[top].c[5][3])) continue; e[top].c[5][4]=num=sum-e[top].c[5][1]-e[top].c[5][2]-e[top].c[5][3]-e[top].c[5][5]; if (num<0||num>9) continue; if (!p.prim(e[top].c[5][1],e[top].c[5][2],e[top].c[5][3],e[top].c[5][4],e[top].c[5][5])) continue; e[top].c[1][4]=num=sum-e[top].c[1][1]-e[top].c[1][2]-e[top].c[1][3]-e[top].c[1][5]; if (num<0||num>9) continue; if (!p.prim(e[top].c[1][1],e[top].c[1][2],e[top].c[1][3],e[top].c[1][4],e[top].c[1][5])) continue; if (!p.prim(e[top].c[1][4],e[top].c[2][4],e[top].c[3][4],e[top].c[4][4],e[top].c[5][4])) continue; top++,e[top]=e[top-1]; } }
写完之后,吐血.
完整代码如下:
#include<bits/stdc++.h> using namespace std; int fir,sum; struct arr{ int c[6][6]; bool operator <(const arr d) const{ for (int i=1;i<=5;i++) for (int j=1;j<=5;j++) if (c[i][j]<d.c[i][j]) return true; else if (c[i][j]>d.c[i][j]) return false; return false; } arr &operator =(const arr d){ for (int i=1;i<=5;i++) for (int j=1;j<=5;j++) c[i][j]=d.c[i][j]; } }e[10000]; int top=0; class prime{ public: int b[100000]; inline void start(int sum){ for (int i=1;i<100000;i++) b[i]=1; for (int i=1;i<10000;i++) b[i]=0; for (int i1=1;i1<=9;i1++) for (int i2=0;i2<=9;i2++) for (int i3=0;i3<=9;i3++) for (int i4=0;i4<=9;i4++) for (int i5=0;i5<=9;i5++){ int num=i1+i2+i3+i4+i5; if (num!=sum) { b[i1*10000+i2*1000+i3*100+i4*10+i5]=false; continue; } num=i1*10000+i2*1000+i3*100+i4*10+i5; for (int i=2;i<=sqrt(num+1);i++) if (num%i==0) { b[num]=false; break; } } } inline bool prim(int i1,int i2,int i3,int i4,int i5){ return b[i1*10000+i2*1000+i3*100+i4*10+i5]; } }p; //建立素数表p inline void into(){ scanf("%d%d",&sum,&fir); memset(e,0,sizeof(e)); p.start(sum); } inline void f13(){ for (int i=0;i<=9;i++){ e[top].c[5][3]=i; int num=sum-e[top].c[2][3]-e[top].c[3][3]-e[top].c[4][3]-e[top].c[5][3]; e[top].c[1][3]=num; if (num<0||num>9) continue; if (!p.prim(num,e[top].c[2][3],e[top].c[3][3],e[top].c[4][3],e[top].c[5][3])) continue; e[top].c[5][4]=num=sum-e[top].c[5][1]-e[top].c[5][2]-e[top].c[5][3]-e[top].c[5][5]; if (num<0||num>9) continue; if (!p.prim(e[top].c[5][1],e[top].c[5][2],e[top].c[5][3],e[top].c[5][4],e[top].c[5][5])) continue; e[top].c[1][4]=num=sum-e[top].c[1][1]-e[top].c[1][2]-e[top].c[1][3]-e[top].c[1][5]; if (num<0||num>9) continue; if (!p.prim(e[top].c[1][1],e[top].c[1][2],e[top].c[1][3],e[top].c[1][4],e[top].c[1][5])) continue; if (!p.prim(e[top].c[1][4],e[top].c[2][4],e[top].c[3][4],e[top].c[4][4],e[top].c[5][4])) continue; top++,e[top]=e[top-1]; } } inline void f12(){ for (int i=0;i<=9;i++){ e[top].c[5][2]=i; int num=sum-e[top].c[2][2]-e[top].c[3][2]-e[top].c[4][2]-e[top].c[5][2]; e[top].c[1][2]=num; if (num<0||num>9) continue; if (p.prim(e[top].c[1][2],e[top].c[2][2],e[top].c[3][2],e[top].c[4][2],e[top].c[5][2])) f13(); } } inline void f11(){ for (int i=0;i<=9;i++){ e[top].c[3][5]=i; int num=sum-e[top].c[3][1]-e[top].c[3][3]-e[top].c[3][4]-e[top].c[3][5]; e[top].c[3][2]=num; if (num<0||num>9) continue; if (!p.prim(e[top].c[3][1],e[top].c[3][2],e[top].c[3][3],e[top].c[3][4],e[top].c[3][5])) continue; e[top].c[4][5]=num=sum-e[top].c[1][5]-e[top].c[2][5]-e[top].c[3][5]-e[top].c[5][5]; if (num<0||num>9) continue; if (!p.prim(e[top].c[1][5],e[top].c[2][5],e[top].c[3][5],num,e[top].c[5][5])) continue; e[top].c[4][3]=num=sum-e[top].c[4][1]-e[top].c[4][2]-e[top].c[4][4]-e[top].c[4][5]; if (num<0||num>9) continue; if (p.prim(e[top].c[4][1],e[top].c[4][2],e[top].c[4][3],e[top].c[4][4],e[top].c[4][5])) f12(); } } inline void f10(){ for (int i=0;i<=9;i++){ e[top].c[3][4]=i; f11(); } } inline void f9(){ for (int i=0;i<=9;i++){ e[top].c[1][5]=i; int num=sum-e[top].c[1][5]-e[top].c[2][4]-e[top].c[3][3]-e[top].c[5][1]; e[top].c[4][2]=num; if (num<0||num>9) continue; if (p.prim(e[top].c[5][1],e[top].c[4][2],e[top].c[3][3],e[top].c[2][4],e[top].c[1][5])) f10(); } } inline void f8(){ for (int i=0;i<=9;i++){ e[top].c[2][5]=i; int num=sum-e[top].c[2][1]-e[top].c[2][2]-e[top].c[2][4]-e[top].c[2][5]; e[top].c[2][3]=num; if (num>9||num<0) continue; if (p.prim(e[top].c[2][1],e[top].c[2][2],e[top].c[2][3],e[top].c[2][4],e[top].c[2][5])) f9(); } } inline void f7(){ for (int i=0;i<=9;i++){ e[top].c[2][4]=i; f8(); } } inline void f6(){ for (int i=1;i<=9;i++){ e[top].c[3][1]=i; int num=sum-e[top].c[1][1]-e[top].c[3][1]-e[top].c[4][1]-e[top].c[5][1]; e[top].c[2][1]=num; if (num<0||num>9) continue; if (p.prim(e[top].c[1][1],e[top].c[2][1],e[top].c[3][1],e[top].c[4][1],e[top].c[5][1])) f7(); } } inline void f5(){ for (int i=1;i<=9;i++){ e[top].c[4][1]=i; f6(); } } inline void f4(){ for (int i=1;i<=9;i++){ e[top].c[5][1]=i; f5(); } } inline void f3(){ for (int i=0;i<=9;i++){ e[top].c[3][3]=i; int num=sum-e[top].c[1][1]-e[top].c[3][3]-e[top].c[4][4]-e[top].c[5][5]; e[top].c[2][2]=num; if (num>9||num<0) continue; if (p.prim(e[top].c[1][1],e[top].c[2][2],e[top].c[3][3],e[top].c[4][4],e[top].c[5][5])) f4(); } } inline void f2(){ for (int i=0;i<=9;i++){ e[top].c[4][4]=i; f3(); } } inline void f1(){ e[++top].c[1][1]=fir; for (int i=0;i<=9;i++){ e[top].c[5][5]=i; f2(); } } inline void work(){ f1(); } inline void outo(){ top--; sort(e+1,e+1+top); for (int i=1;i<=top;i++){ for (int j=1;j<=5;j++){ for (int k=1;k<=5;k++) printf("%d",e[i].c[j][k]); printf("\n"); } printf("\n"); } if (!top) printf("NONE\n"); } int main(){ into(); work(); outo(); return 0; }