prime3.cpp
来自「dd牛的usaco源代码!对学习算法」· C++ 代码 · 共 255 行
CPP
255 行
/*
ID: dd.ener1
PROG: prime3
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <string>
#include <sstream>
using namespace std;
int L,Sum;
int S[1000][5];
int S2[1000][4];
bool V[11][11][11][11][11];
int Now[5][5];
int res[300][5][5];
int N,N2,R;
int Mid[10][1000][4];//中间一数已确定
int MidN[10];
int EENo0[10][10][500][3];//两边两数已确定且没有0
int EENo0N[10][10];
int EE1379[10][10][300][3];//两边两数已确定且仅有1379组成
int EE1379N[10][10];
void input(){
freopen("prime3.in","r",stdin);
scanf("%d%d",&Sum,&L);
}
void add_S(int k){
static char s[6];
sprintf(s,"%d",k);
int sum=0;
for(int i=0;i<5;++i){
s[i]-='0';
sum+=s[i];
}
if(sum!=Sum)return;
for(int i=0;i<5;++i)
S[N][i]=s[i];
++N;
Mid[s[2]][MidN[s[2]]][0]=s[0];
Mid[s[2]][MidN[s[2]]][1]=s[1];
Mid[s[2]][MidN[s[2]]][2]=s[3];
Mid[s[2]][MidN[s[2]]][3]=s[4];
++MidN[s[2]];
if(s[0]==L){
for(int i=0;i<4;++i)
S2[N2][i]=s[i+1];
++N2;
}
if((s[1]%2)&&(s[2]%2)&&(s[3]%2)&&s[1]!=5&&s[2]!=5&&s[3]!=5){
for(int i=0;i<3;++i)
EE1379[s[0]][s[4]][EE1379N[s[0]][s[4]]][i]=s[i+1];
EE1379N[s[0]][s[4]]++;
}
if(s[1]&&s[2]&&s[3]){
for(int i=0;i<3;++i)
EENo0[s[0]][s[4]][EENo0N[s[0]][s[4]]][i]=s[i+1];
EENo0N[s[0]][s[4]]++;
}
}
void gen_S(){
bool pp[100000];
memset(pp,-1,sizeof(pp));
pp[0]=pp[1]=false;
for(int p=2;p<100000;++p){
if(!pp[p])continue;
for(int k=2;k*p<100000;++k)
pp[k*p]=false;
}
N=0;
for(int k=10000;k<=99999;++k)
if(pp[k])add_S(k);
}
void gen_V(){
memset(V,0,sizeof(V));
V[10][10][10][10][10]=true;
for(int i=0;i<N;++i){
int a=S[i][0],b=S[i][1],c=S[i][2],d=S[i][3],e=S[i][4];
const int x=10;
V[a][x][x][x][x]=true;
V[x][b][x][x][x]=true;
V[x][x][c][x][x]=true;
V[x][x][x][d][x]=true;
V[x][x][x][x][e]=true;
V[a][b][x][x][x]=true;
V[a][x][c][x][x]=true;
V[a][x][x][d][x]=true;
V[a][x][x][x][e]=true;
V[x][b][c][x][x]=true;
V[x][b][x][d][x]=true;
V[x][b][x][x][e]=true;
V[x][x][c][d][x]=true;
V[x][x][c][x][e]=true;
V[x][x][x][d][e]=true;
V[a][b][c][x][x]=true;
V[a][b][x][d][x]=true;
V[a][b][x][x][e]=true;
V[a][x][c][d][x]=true;
V[a][x][c][x][e]=true;
V[a][x][x][d][e]=true;
V[x][b][c][d][x]=true;
V[x][b][c][x][e]=true;
V[x][b][x][d][e]=true;
V[x][x][c][d][e]=true;
V[a][b][c][d][x]=true;
V[a][b][c][x][e]=true;
V[a][b][x][d][e]=true;
V[a][x][c][d][e]=true;
V[x][b][c][d][e]=true;
V[a][b][c][d][e]=true;
}
}
void print(){
for(int i=0;i<5;++i){
for(int j=0;j<5;++j)
printf("%d",Now[i][j]);
putchar('\n');
}
putchar('\n');
}
void add_res(){
print();
for(int i=0;i<5;++i)
for(int j=0;j<5;++j)
res[R][i][j]=Now[i][j];
++R;
}
void search6(){//(2,1)(2,3)
for(Now[2][1]=0;Now[2][1]<10;++Now[2][1]){
if(!V[Now[0][1]][Now[1][1]][Now[2][1]][Now[3][1]][Now[4][1]])continue;
for(Now[2][3]=0;Now[2][3]<10;++Now[2][3]){
if(!V[Now[0][3]][Now[1][3]][Now[2][3]][Now[3][3]][Now[4][3]])continue;
if(!V[Now[2][0]][Now[2][1]][Now[2][2]][Now[2][3]][Now[2][4]])continue;
add_res();
}
}
Now[2][1]=Now[2][3]=10;
}
void search5(){//(1,2)(3,2)
for(Now[1][2]=0;Now[1][2]<10;++Now[1][2]){
if(!V[Now[1][0]][Now[1][1]][Now[1][2]][Now[1][3]][Now[1][4]])continue;
for(Now[3][2]=0;Now[3][2]<10;++Now[3][2]){
if(!V[Now[3][0]][Now[3][1]][Now[3][2]][Now[3][3]][Now[3][4]])continue;
if(!V[Now[0][2]][Now[1][2]][Now[2][2]][Now[3][2]][Now[4][2]])continue;
search6();
}
}
Now[1][2]=Now[3][2]=10;
}
void search4(){//枚举上部中间的三个和左边中间的三个
for(int i=EENo0N[Now[0][0]][Now[0][4]]-1;i>=0;--i){
Now[0][1]=EENo0[Now[0][0]][Now[0][4]][i][0];
if(!V[Now[0][1]][Now[1][1]][Now[2][1]][Now[3][1]][Now[4][1]])continue;
Now[0][2]=EENo0[Now[0][0]][Now[0][4]][i][1];
if(!V[Now[0][2]][Now[1][2]][Now[2][2]][Now[3][2]][Now[4][2]])continue;
Now[0][3]=EENo0[Now[0][0]][Now[0][4]][i][2];
if(!V[Now[0][3]][Now[1][3]][Now[2][3]][Now[3][3]][Now[4][3]])continue;
for(int j=EENo0N[Now[0][0]][Now[4][0]]-1;j>=0;--j){
Now[1][0]=EENo0[Now[0][0]][Now[4][0]][j][0];
if(!V[Now[1][0]][Now[1][1]][Now[1][2]][Now[1][3]][Now[1][4]])continue;
Now[2][0]=EENo0[Now[0][0]][Now[4][0]][j][1];
if(!V[Now[2][0]][Now[2][1]][Now[2][2]][Now[2][3]][Now[2][4]])continue;
Now[3][0]=EENo0[Now[0][0]][Now[4][0]][j][2];
if(!V[Now[3][0]][Now[3][1]][Now[3][2]][Now[3][3]][Now[3][4]])continue;
search5();
}
}
Now[0][1]=Now[0][2]=Now[0][3]=Now[1][0]=Now[2][0]=Now[3][0]=10;
}
void search3(){//枚举底部中间的三个和右边中间的三个
if(!EE1379N[Now[0][4]][Now[4][4]]||!EE1379N[Now[4][0]][Now[4][4]])return;
for(int i=EE1379N[Now[4][0]][Now[4][4]]-1;i>=0;--i){
Now[4][1]=EE1379[Now[4][0]][Now[4][4]][i][0];
if(!V[Now[0][1]][Now[1][1]][Now[2][1]][Now[3][1]][Now[4][1]])continue;
Now[4][2]=EE1379[Now[4][0]][Now[4][4]][i][1];
if(!V[Now[0][2]][Now[1][2]][Now[2][2]][Now[3][2]][Now[4][2]])continue;
Now[4][3]=EE1379[Now[4][0]][Now[4][4]][i][2];
if(!V[Now[0][3]][Now[1][3]][Now[2][3]][Now[3][3]][Now[4][3]])continue;
for(int j=EE1379N[Now[0][4]][Now[4][4]]-1;j>=0;--j){
Now[1][4]=EE1379[Now[0][4]][Now[4][4]][j][0];
if(!V[Now[1][0]][Now[1][1]][Now[1][2]][Now[1][3]][Now[1][4]])continue;
Now[2][4]=EE1379[Now[0][4]][Now[4][4]][j][1];
if(!V[Now[2][0]][Now[2][1]][Now[2][2]][Now[2][3]][Now[2][4]])continue;
Now[3][4]=EE1379[Now[0][4]][Now[4][4]][j][2];
if(!V[Now[3][0]][Now[3][1]][Now[3][2]][Now[3][3]][Now[3][4]])continue;
search4();
}
}
Now[4][1]=Now[4][2]=Now[4][3]=Now[1][4]=Now[2][4]=Now[3][4]=10;
}
void search2(){//枚举右上到左下对角线
int M=Now[2][2];
for(int i=MidN[M]-1;i>=0;--i){
Now[0][4]=Mid[M][i][0];
Now[1][3]=Mid[M][i][1];
Now[3][1]=Mid[M][i][2];
Now[4][0]=Mid[M][i][3];
search3();
}
Now[0][4]=Now[1][3]=Now[3][1]=Now[4][0]=10;
}
void search1(){//枚举左上到右下的对角线
for(int i=0;i<N2;++i){
Now[1][1]=S2[i][0];
Now[2][2]=S2[i][1];
Now[3][3]=S2[i][2];
Now[4][4]=S2[i][3];
search2();
}
}
void solve(){
gen_S();
gen_V();
R=0;
for(int i=0;i<5;++i)
for(int j=0;j<5;++j)
Now[i][j]=10;
Now[0][0]=L;
search1();
}
void output(){
freopen("prime3.out","w",stdout);
if(R==0){
puts("NONE");
return;
}
string ss[R];
for(int k=0;k<R;++k){
ostringstream s;
for(int j=0;j<5;++j){
for(int i=0;i<5;++i)
s<<res[k][i][j];
s<<'\n';
}
ss[k]=s.str();
}
sort(ss,ss+R);
for(int k=0;k<R-1;++k)
printf("%s\n",ss[k].c_str());
printf("%s",ss[R-1].c_str());
}
int main(){
freopen("prime3.log","w",stdout);
input();
solve();
output();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?