毒瘤【usaco】素數方陣的總結
阿新 • • 發佈:2018-12-31
這道題的原題大概找得到,自己去找吧.
題目大意就是讓我們找到一個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;
}