质数方阵
Posted fangbozhen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了质数方阵相关的知识,希望对你有一定的参考价值。
https://loj.ac/problem/10024
题目描述
??给出数位之和(S)与左上角的数字(a),要求填出一个(5×5)的质数表,使每行每列每条对角线的数都为质数,并且数位之和为给出的数。
思路
??当初做这道的时候几经崩溃,根本无法在一个(dfs)中在规定时限内完成对质数表的填充,无奈之下,我只能多打几个(dfs)了,具体内容看代码即可。
??我们首先肯定要处理处所有数位和为(S)的质数,这有很多方法,我就不详细讲述了。
??我们考虑填数的时候,尽量填已知多的数,这样可以尽早返回能否填充。既然填的是数位,那么我们就需要质数的判断。我的方法是建一个(5)维的数组。
??所以我们先考虑填左上角开始的横、纵、斜三个质数(现在想来可以先填成三角形状,不过我不想改代码了),再开始搜索。
??(①)填这三个质数,我们可以直接搜索开头为(a)的质数,依次填入。
??(②)我们在尝试填另一条对角线,因为它已知三个数,我们只需依次枚举这两位的数字,判断是否为质数,在进入下一层搜索。
??(③)再同样尝试填第(2)条横线和第(2)条纵线。
??(④)试着填第(3)条横线和第(3)条纵线。
??(⑤)将剩下填完,记录答案。
代码(极长无比的搜索过程)
#include <bits/stdc++.h>
using namespace std;
int p[100000],cnt,m[10],s,v;
struct aa
{
char a[6][6];
}g[5000];
bool cmp(aa x,aa y)
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
if(x.a[i][j]!=y.a[i][j])return x.a[i][j]<y.a[i][j];
}
bool is_prime(int x)
{
for(int i=2;i<=sqrt(x);i++)
if(x%i==0)return 0;
return 1;
}
int sum(int x)
{
int s=0;
while(x)
{
s+=x%10;
x/=10;
}
return s;
}
bool f,fhash[10][10][10][10][10],ff[100000];
char ans[10][10];
bool check()
{
for(int i=0;i<5;i++)
{
int x=0,ss=0;
for(int j=0;j<5;j++)
x=x*10+ans[i][j]-'0',ss+=ans[i][j]-'0';
if(ss!=s||!ff[x])return 0;
}
for(int j=0;j<5;j++)
{
int x=0,ss=0;
for(int i=0;i<5;i++)
x=x*10+ans[i][j]-'0',ss+=ans[i][j]-'0';
if(ss!=s||!ff[x])return 0;
}
return 1;
}
void dfs7()
{
int a=ans[0][3]-'0',b=ans[1][3]-'0',c=ans[2][3]-'0',d=ans[3][3]-'0';
for(int i=0;i<10;i++)
if(fhash[a][b][c][d][i])
{
ans[4][3]=i+'0';
if(check())
{
f=1;
v++;
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
g[v].a[i][j]=ans[i][j];
}
}
}
void dfs6()
{
int a=ans[3][0]-'0',b=ans[3][1]-'0',c=ans[3][2]-'0',d=ans[3][3]-'0';
for(int i=0;i<10;i++)
if(fhash[a][b][c][d][i])
{
ans[3][4]=i+'0';
dfs7();
}
}
void dfs5()
{
int a=ans[0][2]-'0',b=ans[1][2]-'0',c=ans[2][2]-'0';
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
if(fhash[a][b][c][i][j])
{
ans[3][2]=i+'0';ans[4][2]=j+'0';
dfs6();
}
}
void dfs4()
{
int a=ans[2][0]-'0',b=ans[2][1]-'0',c=ans[2][2]-'0';
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
if(fhash[a][b][c][i][j])
{
ans[2][3]=i+'0';ans[2][4]=j+'0';
dfs5();
}
}
void dfs3()
{
int a=ans[0][1]-'0',b=ans[1][1]-'0',c=ans[3][1]-'0';
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
if(fhash[a][b][i][c][j])
{
ans[2][1]=i+'0';ans[4][1]=j+'0';
dfs4();
}
}
void dfs2()
{
int a=ans[1][0]-'0',b=ans[1][1]-'0',c=ans[1][3]-'0';
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
if(fhash[a][b][i][c][j])
{
ans[1][2]=i+'0';ans[1][4]=j+'0';
dfs3();
}
}
void dfs1()
{
int a=ans[4][0]-'0',b=ans[2][2]-'0',c=ans[0][4]-'0';
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
if(fhash[a][i][b][j][c])
{
ans[3][1]=i+'0';ans[1][3]=j+'0';
dfs2();
}
}
int main()
{
// freopen("aa.txt","w",stdout);
int x,k=0;
scanf("%d%d",&s,&x);
for(int i=10000;i<100000;i++)
if(is_prime(i)&&sum(i)==s)
{
p[++k]=i;
int a[8]={0},l=i;
for(int j=5;j>0;j--)
a[j]=l%10,l/=10;
fhash[a[1]][a[2]][a[3]][a[4]][a[5]]=1;
ff[i]=1;
}
cnt=k-1;
for(int i=1;i<=9;i++)
m[i]=lower_bound(p+1,p+cnt+1,i*10000)-p;
// printf("%d
",cnt);
// for(int i=1;i<=cnt;i++)
// printf("%d
",p[i]);
ans[0][0]=x+'0';
for(int i=m[x];i<m[x+1];i++)
for(int j=m[x];j<m[x+1];j++)
for(int k=m[x];k<m[x+1];k++)
{
int l=p[i];
// printf("%d
",l);
for(int q=4;q>0;q--)
ans[0][q]=l%10+'0',l/=10;
l=p[j];
for(int q=4;q>0;q--)
ans[q][0]=l%10+'0',l/=10;
l=p[k];
for(int q=4;q>0;q--)
ans[q][q]=l%10+'0',l/=10;
// printf("%s
",ans[0]);
dfs1();
}
if(!f)printf("NONE");
else
{
sort(g+1,g+v+1,cmp);
for(int i=1;i<=v;i++)
{
for(int j=0;j<5;j++)
printf("%s
",g[i].a[j]);
printf("
");
}
}
return 0;
}
以上是关于质数方阵的主要内容,如果未能解决你的问题,请参考以下文章