IOI'94
In the square below, each row, each column and the two diagonals can be read as a five digit prime number. The rows are read from left to right. The columns are read from top to bottom. Both diagonals are read from left to right.
+---+---+---+---+---+ | 1 | 1 | 3 | 5 | 1 | +---+---+---+---+---+ | 3 | 3 | 2 | 0 | 3 | +---+---+---+---+---+ | 3 | 0 | 3 | 2 | 3 | +---+---+---+---+---+ | 1 | 4 | 0 | 3 | 3 | +---+---+---+---+---+ | 3 | 3 | 3 | 1 | 1 | +---+---+---+---+---+
- The prime numbers' digits must sum to the same number.
- The digit in the top left-hand corner of the square is pre-determined (1 in the example).
- A prime number may be used more than once in the same square.
- If there are several solutions, all must be presented (sorted in numerical order as if the 25 digits were all one long number).
- A five digit prime number cannot begin with a zero (e.g., 00003 is NOT a five digit prime number).
PROGRAM NAME: prime3
INPUT FORMAT
A single line with two space-separated integers: the sum of the digits and the digit in the upper left hand corner of the square.
SAMPLE INPUT (file prime3.in)
11 1
OUTPUT FORMAT
Five lines of five characters each for each solution found, where each line in turn consists of a five digit prime number. Print a blank line between solutions. If there are no prime squares for the input data, output a single line containing "NONE".
SAMPLE OUTPUT (file prime3.out)
The above example has 3 solutions.
11351 14033 30323 53201 13313 11351 33203 30323 14033 33311 13313 13043 32303 50231 13331
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
FILE *fin,*fout;
int Prime[100000],PrimeC;
int Flag[10][10][10][10][10];
int Number[1000][5];
int Sum,First;
int Save[5][5];
int Ans[100][5][5];
int AnsC=0;
int comp(int i,int j)
{
int x=0,y=0;
while(x<5&&Ans[i][x][y]==Ans[j][x][y]){
y++;
if(y==5){
y=0;
x++;
}
}
if(x==5)
return 0;
return Ans[i][x][y]>Ans[j][x][y];
}
void Sort()
{
int i,j,k,t;
for(i=1;i<AnsC;i++){
for(j=0;j<5;j++)
for(k=0;k<5;k++)
Ans[AnsC][j][k]=Ans[i][j][k];
for(j=i;j>0&&comp(j-1,AnsC);j--)
for(k=0;k<5;k++)
for(t=0;t<5;t++)
Ans[j][k][t]=Ans[j-1][k][t];
for(k=0;k<5;k++)
for(t=0;t<5;t++)
Ans[j][k][t]=Ans[AnsC][k][t];
}
}
int IsSum(int N)
{
int sum=0;
while(N!=0){
sum+=N%10;
N/=10;
}
return sum==Sum;
}
void SaveAns()
{
int i,j;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
Ans[AnsC][i][j]=Save[i][j];
AnsC++;
}
void Print()
{
int i,j,k;
if(AnsC==0)
fprintf(fout,"NONE\n");
else{
for(i=0;i<AnsC;i++){
for(j=0;j<5;j++){
for(k=0;k<5;k++)
fprintf(fout,"%d",Ans[i][j][k]);
fprintf(fout,"\n");
}
if(i!=AnsC-1)
fprintf(fout,"\n");
}
}
}
void DFS(int Depth)
{
int i,j;
int x41,x43,x14,x34,x03,x30,x21,x23,x20,x24;
switch(Depth){ //0,1对角线,2中间的竖,3上的横
case 0:for(i=0;i<PrimeC;i++){
if(Number[i][0]==First){
for(j=0;j<5;j++)
Save[j][j]=Number[i][j];
DFS(Depth+1);
}
}break;
case 1:for(i=0;i<PrimeC;i++){
if(Number[i][2]==Save[2][2]&&Number[i][4]!=0){
for(j=0;j<5;j++)
Save[4-j][j]=Number[i][j];
DFS(Depth+1);
}
}break;
case 2:for(i=0;i<PrimeC;i++){
if(Number[i][2]==Save[2][2]){
for(j=0;j<5;j++)
Save[j][2]=Number[i][j];
DFS(Depth+1);
}
}break;
case 3:for(i=1;i<=9;i++){
x03=Sum-Save[0][0]-i-Save[0][2]-Save[0][4];
if(x03<=0||x03>9)
continue;
if(Flag[Save[0][0]][i][Save[0][2]][x03][Save[0][4]]){
Save[0][1]=i;
Save[0][3]=x03;
DFS(Depth+1);
}
}break;
case 4:for(i=0;i<=9;i++){
x21=Sum-Save[0][1]-Save[1][1]-Save[3][1]-i;
if(x21<0||x21>9)
continue;
if(Flag[Save[0][1]][Save[1][1]][x21][Save[3][1]][i]){
Save[2][1]=x21;
Save[4][1]=i;
DFS(Depth+1);
}
}break;
case 5: x43=Sum-Save[4][0]-Save[4][1]-Save[4][2]-Save[4][4];
if(x43<0||x43>9)
break;
if(Flag[Save[4][0]][Save[4][1]][Save[4][2]][x43][Save[4][4]]){
Save[4][3]=x43;
DFS(Depth+1);
}break;
case 6:x23=Sum-Save[0][3]-Save[1][3]-Save[3][3]-Save[4][3];
if(x23<0||x23>9)
break;
if(Flag[Save[0][3]][Save[1][3]][x23][Save[3][3]][Save[4][3]]){
Save[2][3]=x23;
DFS(Depth+1);
}break;
case 7:for(i=1;i<=9;i++){
x14=Sum-i-Save[1][1]-Save[1][2]-Save[1][3];
if(x14<0||x14>9)
continue;
if(Flag[i][Save[1][1]][Save[1][2]][Save[1][3]][x14]){
Save[1][0]=i;
Save[1][4]=x14;
DFS(Depth+1);
}
}break;
case 8:for(i=1;i<=9;i++){
x34=Sum-i-Save[3][1]-Save[3][2]-Save[3][3];
if(x34<0||x34>9)
continue;
if(Flag[i][Save[3][1]][Save[3][2]][Save[3][3]][x34]){
Save[3][0]=i;
Save[3][4]=x34;
// Print2(Depth);
DFS(Depth+1);
}
}break;
case 9:x20=Sum-Save[0][0]-Save[1][0]-Save[3][0]-Save[4][0];
x24=Sum-Save[0][4]-Save[1][4]-Save[3][4]-Save[4][4];
if(x20<=0||x24<0||x20>9||x24>9)
break;
if(Flag[x20][Save[2][1]][Save[2][2]][Save[2][3]][x24]
&&Flag[Save[0][0]][Save[1][0]][x20][Save[3][0]][Save[4][0]]
&&Flag[Save[0][4]][Save[1][4]][x24][Save[3][4]][Save[4][4]]){
Save[2][0]=x20;
Save[2][4]=x24;
// Print2(Depth);
DFS(Depth+1);
}break;
case 10:SaveAns();break;
}
}
int main()
{
int i,j,k;
fin=fopen("prime3.in","r");
fout=fopen("prime3.out","w");
memset(Prime,0,sizeof(Prime));
memset(Flag,0,sizeof(Flag));
fscanf(fin,"%d %d",&Sum,&First);
//筛选法求五位的素数
for(i=2;i<=50000;i++)
for(j=2;i*j<100000;j++)
Prime[i*j]=1;
for(i=10000,j=0;i<100000;i++)
if(Prime[i]==0&&IsSum(i))
Prime[j++]=i;
PrimeC=j;
//保存素数
for(i=0;i<PrimeC;i++){
for(j=0,k=1;j<5;j++){
Number[i][4-j]=(Prime[i]/k)%10;
k*=10;
}
}
//记录素数
for(i=0;i<PrimeC;i++)
Flag[Number[i][0]][Number[i][1]][Number[i][2]][Number[i][3]][Number[i][4]]=1;
DFS(0);
Sort();
Print();
return 0;
}
先用筛选法求出所有五位的素数,然后开一个五位数组记录是否该数是为素数
最后DFS,搜索过程中要按照顺序可以极大的节约时间,先对角线,然后中间的竖线,接着最上面一行和最下面一行。然后通过减法算出第二列和第四列,最后搜索第二行第四行,减法得到中间一行结束。