毒瘤【usaco】素数方阵的总结

这道题的原题大概找得到,自己去找吧.

题目大意就是让我们找到一个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;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/79824861