预处理+搜索剪枝。
4*4的边界上的数字必须是奇数。
/* 1979 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 typedef struct node_t {
char s[]; node_t() {}
node_t(int a[][]) {
int l = ;
rep(i, , )
rep(j, , )
s[l++] = a[i][j]+'';
s[l] = '\0';
} friend bool operator< (const node_t& a, const node_t& b) {
return strcmp(a.s, b.s)< ? true:false;
} friend bool operator== (const node_t& a, const node_t& b) {
return strcmp(a.s, b.s)==;
} friend bool operator!= (const node_t& a, const node_t& b) {
return strcmp(a.s, b.s)!=;
} void print() {
for (int i=; i<; i+=) {
for (int j=; j<; ++j)
putchar(s[i+j]);
putchar('\n');
}
} } node_t; const int maxn = ;
bool isPrime[maxn];
bool valid[maxn];
int a[maxn], an;
int b[maxn], bn;
int c[maxn], cn;
bool M03[][];
vector<node_t> ans;
vi AV21[];
vi AV30[];
vi CV21[];
vi CV30[];
int M[][]; void getV(int* a, int n, vi vc30[], vi vc21[]) {
int d[]; rep(i, , n) {
int x = a[i];
rep(j, , ) {
d[j] = x % ;
x /= ;
}
int v30 = d[]*+d[];
int v21 = d[]*+d[];
vc30[v30].pb(v21);
vc21[v21].pb(v30);
} vi::iterator iter;
rep(i, , ) {
sort(all(vc30[i]));
iter = unique(all(vc30[i]));
vc30[i].erase(iter, vc30[i].end()); sort(all(vc21[i]));
iter = unique(all(vc21[i]));
vc21[i].erase(iter, vc21[i].end());
}
} void init() {
int i, j, k;
int x;
int d[]; an = bn = cn = ;
memset(isPrime, true, sizeof(isPrime));
memset(valid, false, sizeof(valid));
isPrime[] = isPrime[] = false; for (i=; i<maxn; ++i) {
if (isPrime[i]) {
b[bn++] = i;
for (j=i*i; j<maxn; j+=i)
isPrime[j] = false;
}
} memset(M03, false, sizeof(M03));
for (i=; i<bn; ++i) {
x = b[i];
if (valid[x])
continue;
for (j=; j<; ++j) {
d[j] = x % ;
x /= ;
}
if ((d[]&)== || (d[]&)==)
continue;
x = ;
for (j=; j<; ++j) {
x = x * + d[j];
}
if (isPrime[x]) {
valid[x] = valid[b[i]] = true;
a[an++] = x;
a[an++] = b[i];
M03[d[]][d[]] = M03[d[]][d[]] = true;
bool flag = true;
for (j=; j<; ++j) {
if ((d[j] & )==) {
flag = false;
break;
}
}
if (flag) {
c[cn++] = x;
c[cn++] = b[i];
}
}
} sort(a, a+an);
an = unique(a, a+an) - a;
sort(c, c+cn);
cn = unique(c, c+cn) - c; getV(a, an, AV30, AV21);
getV(c, cn, CV30, CV21);
} void solve_() {
int v30 = *M[][]+M[][];
int v30_ = *M[][]+M[][]; int sz = SZ(AV30[v30]);
int sz_ = SZ(AV30[v30_]);
rep(i, , sz) {
int v21 = AV30[v30][i];
M[][] = v21/;
M[][] = v21%;
rep(j, , sz_) {
int v21_ = AV30[v30_][j];
M[][] = v21_/;
M[][] = v21_%; int v1 = M[][]*+*M[][]+M[][]*+M[][];
int v2 = M[][]*+*M[][]+M[][]*+M[][];
int v3 = M[][]*+*M[][]+M[][]*+M[][];
int v4 = M[][]*+*M[][]+M[][]*+M[][]; if (valid[v1] && valid[v2] && valid[v3] && valid[v4]) {
ans.pb(node_t(M));
}
}
}
} void solve() {
int d1[];
int d2[];
int d3[]; rep(i, , cn) {
int x = c[i];
rep(dd, , ) {
d1[dd] = x % ;
x /= ;
}
int f1 = d1[];
int e1 = d1[];
rep(j, , cn) {
int x = c[j];
rep(dd, , ) {
d2[dd] = x % ;
x /= ;
}
int f2 = d2[];
int e2 = d2[];
if (f1 != f2)
continue;
rep(k, , cn) {
int x = c[k];
rep(dd, , ) {
d3[dd] = x % ;
x /= ;
}
int f3 = d3[];
int e3 = d3[];
if (f3 != e1)
continue; int v30 = e2* + e3;
int sz_CV30 = SZ(CV30[v30]);
rep(ii, , sz_CV30) {
int v21 = CV30[v30][ii];
int x3 = v21/;
int y3 = v21%; M[][] = d1[];
M[][] = d1[];
M[][] = d1[];
M[][] = d1[]; M[][] = d2[];
M[][] = d2[];
M[][] = d2[]; M[][] = d3[];
M[][] = d3[];
M[][] = d3[]; M[][] = x3;
M[][] = y3; solve_();
}
}
}
}
} void print() {
sort(all(ans));
vector<node_t>::iterator iter = unique(all(ans));
ans.erase(iter, ans.end());
int sz = SZ(ans);
ans[].print();
rep(i, , sz) {
putchar('\n');
ans[i].print();
}
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif init();
solve();
print(); #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}