1. 程式人生 > >毒瘤【usaco】素數方陣的總結

毒瘤【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;
}