关于 DFS
深搜与剪枝
前言
12.26晚上做了一下埃及分数之后没有在继续做题
(经过yjk大大的提醒 我发现埃及分数过不了是因为我欠揍的不开long long)
然后对前面的题目稍微整理了一下
丢到下面(发现自己越来越懒 连题目都懒得搬了)
如果发现有什么错误 欢迎各位带着证据 丢掉素质的来干掉博主
12.27 补充题目(越来越懒)
1. 数的划分
书上有说是上下界剪枝
但是当时自己打的那个没有用到上界 直接以剩余数的大小作为上界 依旧能过
下界:
不考虑顺序 所以每一个节点不小于前一个节点
上界:
按照刚刚的下界枚举 枚举的顺序显然是单调的
假设将n已经分解为\(a[1], a[2], ... , a[i - 1]\) 则 \(a[i]\) 不可能在取到比 $n/(m - i +1) $ 更大
(这里我感觉这个n可以进一步的优化为当前剩余的数)
code:
/*
Time: 12.20
Worker: Blank_space
Source: #10018. 「一本通 1.3 例 1」数的划分
*/
/*--------------------------------------------*/
#include<cstdio>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, k, ans;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void dfs(int t, int path, int sum)
{
if(t - 1 == k) {if(sum == 0) ans++; return ;}
for(int i = path; i <= sum; i++)
dfs(t + 1, i, sum - i);
}
/*----------------------------------------函数*/
int main()
{
n = read(); k = read();
dfs(1, 1, n);
printf("%d", ans);
return 0;
}
2. 生日蛋糕
很明显的 枚举半径与高度 累计 最后判断
考虑剪枝
分析题目:
每一层的一定比上面的那一层的高度和半径大 考虑从下到上倒序枚举
再看:
在外层枚举 R 当 R 确定时 就有了H的上界
上下界剪枝:
再看:
化简:
为方便剪枝 不妨在搜索过程中计算 S 将\(R^2\)单独拿出来
所以搜索到第 i 层的 S 为:
再往上搜索的时候 一定有:
所以如果再往上的所有层都以当前层的半径和高度计算仍达不到所要求的体积 就无需考虑了
可行性剪枝:
(这里与代码里的不太一样 这是后来写的)
这里一边搜索一边统计答案
所以不难想到 另一个 也就是最优性剪枝
因为所有的数都是整数 如果还有 x 层没有处理的话 那么这 x 层的最小贡献则是 x
所以 当:
时 继续搜下去所产生的答案已经不会更优了 就可以进行剪枝
我只用到了这三个剪枝 与书上的又一定的出入 书上的五个更加详细 也比较神奇
code:
/*
Time: 12.20
Worker: Blank_space
Source: #10019. 「一本通 1.3 例 2」生日蛋糕
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, m, a[30], b[30], sum, ans = INF;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void dfs(int t, int v, int z, int sum)
{
if(v < 0) return ;
if(sum + z > ans - a[1] * a[1]) return ;
if(v - a[t - 1] * a[t - 1] * b[t - 1] * z > 0) return ;
if(t == m + 1)
{
if(v == 0)
{
sum += a[1] * a[1];
ans = min(ans, sum);
}
return ;
}
for(int i = a[t - 1] - 1; i >= z; i--)
{
for(int j = min(b[t - 1] - 1, v / (i * i) + 1); j >= z; j--)
{
a[t] = i; b[t] = j;
dfs(t + 1, v - i * i * j, z - 1, sum + 2 * a[t] * b[t]);
}
}
}
/*----------------------------------------函数*/
int main()
{
n = read(); m = read();
a[0] = b[0] = sqrt(n);
dfs(1, n, m, 0);
printf("%d", ans == INF ? 0 : ans);
return 0;
}
3. 小木棍
枚举所有可能的长度 判断是否能够凑出整数个的长度 再在能凑出的里面取最小的
这... 这必挂
考虑剪枝:
首先 木棒的长度一定都是整数的 数量也是整数的
求一下所有木棍的长度和 枚举截取的长度 满足能够整除所有木棍的长度和
枚举的边界:
原木棍的长度一定大于所有木棍中最长的那一根
然后我们有了原始每一根木棍的长度
在拼凑进行选用木棍时 很显然 较短的木棍要比长的木棍更加灵活
所以在拼凑时优先使用较长的木棍 较短的木棍可能在后面能用到
所以对木棍进行由大到小排序 从大到小取用
同时 排完序之后 木棍中的相同长度的木棍都放到一起了 而若是一根木棍匹配失败 那么相同长度的木棍也必定不可能成功了 相同长度的木棍不做重复判断 直接剪枝
还有两个似乎有点用的 题解上的剪枝 单独拿出来很难解释
把dfs函数拿出来说吧
bool dfs(int t, int sl, int path)
{
if(t > s) return 1;
if(sl == len) return dfs(t + 1, 0, 0);
int f = 0;
for(int i = path; i <= n; i++)
{
if(vis[i]) continue;
if(sl + a[i] > len) continue;
if(f == a[i]) continue;
vis[i] = 1;
if(dfs(t, sl + a[i], i)) return 1;
vis[i] = 0; f = a[i];
if(sl == 0 || sl + a[i] == len) return 0;
}
return 0;
}
上面第十四行的位置
首先 前面:
如果代码已经运行到了这个位置 并且还没有能用的 那还找个鬼 第一个分支就失败了 后面的必挂
然后 后面:
代码运行到了这个位置 还是能找到能进行成功匹配的木棍 则这根木棍必然是和刚刚的一样的 是重复匹配 就不用了关了
code:
/*
Time: 12.20
Worker: Blank_space
Source: #10020. 「一本通 1.3 例 3」小木棍
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, a[70], sum, len, ans = INF, s, maxx;
bool vis[70];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
bool cmp(int x, int y) {return x > y;}
bool dfs(int t, int sl, int path)
{
if(t > s) return 1;
if(sl == len) return dfs(t + 1, 0, 0);
int f = 0;
for(int i = path; i <= n; i++)
{
if(vis[i]) continue;
if(sl + a[i] > len) continue;
if(f == a[i]) continue;
vis[i] = 1;
if(dfs(t, sl + a[i], i)) return 1;
vis[i] = 0; f = a[i];
if(sl == 0 || sl + a[i] == len) return 0;
}
return 0;
}
/*----------------------------------------函数*/
int main()
{
n = read();
for(int i = 1; i <= n; i++) a[i] = read(), sum += a[i], maxx = max(maxx, a[i]);
sort(a + 1, a + 1 + n, cmp);
for(int i = maxx; i <= sum; i++)
{
if(sum % i) continue;
s = sum / i;
len = i;
memset(vis, 0, sizeof vis);
if(dfs(1, 0, 0))
{
printf("%d", len);
return 0;
}
}
return 0;
}
4. Addition Chains
这个题目第一遍写的搜索直接就是按照倒序搜的 还没想优化 但是由于LOJ上的数据太水 跑过了(书上介绍的也确实就是优化搜索顺序 没有其他) 但是在洛谷上过不去 所以写的迭代加深 然后正序搜索 就挂了... (差了3ms)改成倒序的可以过
这个题的迭代加深有个其他的优化
假设当前搜到了第 t 层 最大深度是 maxd
因为数列最后一个数一定是这一个数列中最大的数
所以:
所以当这个数扩大 2 的\((maxd - t + 1)\) 仍不满足条件时就可以直接剪枝了
code:
首先是一般搜索
/*
Time: 12.20
Worker: Blank_space
Source: #10021. 「一本通 1.3 例 4」Addition Chains
*/
/*--------------------------------------------*/
#include<cstdio>
#include<iostream>
#include<string.h>
#define int long long
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int _n, a[B], num, b[B];
bool p;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void dfs(int t)
{
if(t > num) return ;
if(a[t - 1] * (1 << num - t + 1) < _n) return ;
if(a[t - 1] == _n)
{
if(t - 1 < num)
{
num = t - 1;
for(int i = 1; i < t; i++) b[i] = a[i];
}
return ;
}
for(int i = t - 1; i >= 1; i--)
{
for(int j = i; j >= 1; j--)
{
if(a[i] + a[j] > _n) continue;
if(a[i] + a[j] <= a[t - 1]) {p = 1; break;}
if(a[i] + a[j] <= _n) a[t] = a[i] + a[j];
dfs(t + 1);
}
if(p){p = 0; break;}
}
}
/*----------------------------------------函数*/
signed main()
{
while(cin >> _n && _n)
{
memset(a, 0, sizeof a);
num = INF; p = 0; a[1] = 1; dfs(2);
for(int i = 1; i <= num; i++) printf("%lld ", b[i]);
printf("\n");
}
return 0;
}
迭代加深:
/*
Time: 12.20
Worker: Blank_space
Source: #10021. 「一本通 1.3 例 4」Addition Chains
*/
/*--------------------------------------------*/
#include<cstdio>
#include<iostream>
#include<string.h>
#define int long long
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int _n, a[B], maxd;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
bool dfs(int t)
{
if(t > maxd) return a[t - 1] == _n;
if(a[t - 1] * (1 << maxd - t + 1) < _n) return 0;
for(int i = t - 1; i >= 0; i--)
for(int j = i; j >= 0; j--)
{
if(a[i] + a[j] > _n) continue;
if(a[i] + a[j] <= a[t - 1]) break;
a[t] = a[i] + a[j];
if(dfs(t + 1)) return 1;
}
return 0;
}
/*----------------------------------------函数*/
signed main()
{
while(cin >> _n && _n)
{
a[0] = 1;
if(_n == 1) {puts("1"); continue;}
while(++maxd)
if(dfs(1))
{
for(int i = 0; i <= maxd; i++) printf("%lld ", a[i]);
printf("\n");
maxd = 0;
break;
}
}
return 0;
}
5. weight
/*
Time: 12.26
Worker: Blank_space
Source: #10249. 「一本通 1.3 例 5」weight
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, c[2010], m, k[C], a[2010], b[2010], ans[2010], num;
bool p;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void dfs(int t, int num1, int num2)
{
if(t == 2 * n + 1) {p = 1; return ;}
if(num2 < num1 && a[num1] + b[num1 + 1] != c[n * 2]) return ;
if(k[c[t] - a[num1]] && num1 < n)
{
a[num1 + 1] = c[t];// num++;
// ans[num1 + 1] = c[t] - a[num1];
dfs(t + 1, num1 + 1, num2);
if(p) return ;
}
if(k[c[t] - b[num2]] && num2 > 1)
{
b[num2 - 1] = c[t];// num++;
// ans[num2 - 1] = c[t] - b[num2];
dfs(t + 1, num1, num2 - 1);
if(p) return ;
}
}
/*----------------------------------------函数*/
int main()
{
// freopen("weight7.in", "r", stdin);
n = read();
for(int i = 1; i <= 2 * n; i++) c[i] = read();
m = read();
for(int i = 1; i <= m; i++) {int x = read(); k[x] = 1;}
sort(c + 1, c + 1 + 2 * n);
dfs(1, 0, n + 1);
for(int i = 1; i <= n; i++) printf("%d ", a[i] - a[i - 1]);
return 0;
}
6. 埃及分数
/*
Time: 12.26
Worker: Blank_space
Source: #10022. 「一本通 1.3 练习 1」埃及分数
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int x, y, n, a[C], maxd, ans[C];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int gcd(int _x, int _y) { return _y ? gcd(_y, _x % _y) : _x; }
bool dfs(int _x, int _y, int _z, int t)
{
if(t == maxd)
{
if(_x == 1 && _y > a[t - 1] && (_y < ans[t] || !ans[t]))
{
for(int i = 1; i <= t; i++) ans[i] = a[i];
ans[t] = _y;
return 1;
}
return 0;
}
bool p = 0;
for(int i = max(_z + 1, y / x + 1); _y * (maxd - t + 1) > _x * i; i++)
{
if(_x * i < _y) continue ;
a[t] = i;
int xx = _x * i - _y, yy = _y * i;
int zz = gcd(xx, yy);
if(dfs(xx / zz, yy / zz, i, t + 1)) p = 1;
}
return p;
}
/*----------------------------------------函数*/
signed main()
{
x = read(); y = read();
int z = gcd(x, y);
x /= z; y/= z;
if(x == 1) {printf("%d", y); return 0;}
while(++maxd)
{
if(dfs(x, y, 1, 1))
{
for(int i = 1; i <= maxd; i++) printf("%d ", ans[i]);
break;
}
}
return 0;
}
7. 平板涂色
/*
Time:
Worker: Blank_space
Source:
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
#include<string.h>
#define emm(x) memset(x, 0, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, mp[20][20], ans = INF, sum, c[30], cnt, maxc;
struct node {
int x_1, y_1, x_2, y_2, c;
}a[20];
bool vis[20], p, visc[30];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void f(int k, int opt)
{
for(int i = a[k].x_1; i <= a[k].x_2; i++)
for(int j = a[k].y_1; j <= a[k].y_2; j++)
mp[i][j] = opt;
}
bool check(int k)
{
for(int i = a[k].x_1; i <= a[k].x_2; i++)
if(!mp[i][a[k].y_1 - 1]) return 0;
return 1;
}
void print()
{
for(int i = 0; i <= 10; i++)
{
for(int j = 0; j <= 10; j++)
printf("%d ", mp[i][j]);
puts("");
}
puts("");
}
void dfs(int sum, int num, int cl)
{
if(num > ans) return ;
if(sum == n) {ans = min(ans, num); return ;}
for(int i = 1; i <= n; i++)
{
if(vis[i] || !check(i)) continue;
f(i, 1); vis[i] = 1;
if(a[i].c == cl) dfs(sum + 1, num, cl);
else dfs(sum + 1, num + 1, a[i].c);
f(i, 0); vis[i] = 0;
}
}
/*----------------------------------------函数*/
int main()
{
n = read();
for(int i = 1; i <= n; i++)
a[i].y_1 = read() + 1, a[i].x_1 = read() + 1, a[i].y_2 = read(), a[i].x_2 = read(), a[i].c = read();
for(int i = 0; i <= 10; i++) mp[i][0] = mp[0][i] = 1;
dfs(0, 0, 0);
printf("%d", ans);
return 0;
}
最后一个靶形数独没有做
质数方阵只有四十分
8. 质数方阵
/*
Time: 12.27
Worker: Blank_space
Source: #10024. 「一本通 1.3 练习 3」质数方阵
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
using namespace std;
/*--------------------------------------头文件*/
const int O = 1e6 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, k, c[O], cnt, a[1010][10], _cnt = 1, mp[10][10], b[10], tot;
struct node {
bool operator < (const node & x) const
{
return h[1] == x.h[1] ? h[2] == x.h[2] ? h[3] == x.h[3] ? h[4] == x.h[4] ? h[5] < x.h[5] : h[4] < x.h[4] : h[3] < x.h[3] : h[2] < x.h[2] : h[1] < x.h[1];
}
int h[6];
}ans[6];
bool vis[O];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void prime()
{
for(int i = 2; i <= 1e5; i++)
{
if(!vis[i]) c[++cnt] = i;
for(int j = 1; j <= cnt && i * c[j] <= 1e5; j++)
{
vis[i * c[j]] = 1;
if(!(i % c[j])) break;
}
}
}
void dfs1(int t, int s, int sum)
{
if(t == 5)
{
if(!(s % 2) || !(s % 5)) return ;
sum = sum * 10 + s;
if(vis[sum]) return ;
for(int i = 1; i <= 4; i++) a[_cnt][i] = b[i];
a[_cnt][0] = sum; a[_cnt++][5] = s;
return ;
}
for(int i = t == 1 ? 1 : 0; i <= 9; i++)
{
if(i >= s) continue;
b[t] = i;
dfs1(t + 1, s - i, sum * 10 + i);
}
}
void getans()
{
tot++;
for(int i = 1; i <= 5; i++)
{
int _sum = 0;
for(int j = 1; j <= 5; j++)
_sum = _sum * 10 + mp[i][j];
ans[tot].h[i] = _sum;
}
}
void print()
{
for(int i = 1; i <= tot; i++)
{
for(int j = 1; j <= 5; j++) printf("%d\n", ans[i].h[j]);
puts("");
}
}
void dfs2()
{
for(int A = 1; A <= _cnt; A++)
{
if(a[A][1] != k) continue;
for(int B = 1; B <= 5; B++) mp[B][B] = a[A][B];
for(int B = 1; B <= _cnt; B++)
{
if(a[B][5] != mp[5][5]) continue;
for(int C = 1; C <= 4; C++) mp[C][5] = a[B][C];
for(int C = 1; C <= _cnt; C++)
{
if(a[C][4] != mp[4][4] || a[C][5] != mp[4][5]) continue;
for(int D = 1; D <= 3; D++) mp[4][D] = a[C][D];
for(int D = 1; D <= _cnt; D++)
{
if(a[D][3] != mp[3][3] || a[D][5] != mp[3][5]) continue;
mp[3][1] = a[D][1]; mp[3][2] = a[D][2]; mp[3][4] = a[D][4];
for(int E = 1; E <= _cnt; E++)
{
if(a[E][2] != mp[4][2] || a[E][3] != mp[3][3] || a[E][5] != mp[1][5]) continue;
mp[5][1] = a[E][1]; mp[2][4] = a[E][4];
for(int F = 1; F <= _cnt; F++)
{
if(a[F][1] != mp[1][1] || a[F][3] != mp[3][1] || a[F][4] != mp[4][1] || a[F][5] != mp[5][1]) continue;
mp[2][1] = a[F][2];
for(int G = 1; G <= _cnt; G++)
{
if(a[G][1] != mp[2][1] || a[G][2] != mp[2][2] || a[G][4] != mp[2][4] || a[G][5] != mp[2][5]) continue;
mp[2][3] = a[G][3];
for(int H = 1; H <= _cnt; H++)
{
if(a[H][2] != mp[2][2] || a[H][3] != mp[3][2] || a[H][4] != mp[4][2]) continue;
mp[1][2] = a[H][1]; mp[5][2] = a[H][5];
for(int J = 1; J <= _cnt; J++)
{
if(a[J][2] != mp[2][3] || a[J][3] != mp[3][3] || a[J][4] != mp[4][3]) continue;
mp[1][3] = a[J][1]; mp[5][3] = a[J][5];
for(int K = 1; K <= _cnt; K++)
{
if(a[K][2] != mp[2][4] || a[K][3] != mp[3][4] || a[K][4] != mp[4][4]) continue;
mp[1][4] = a[K][1]; mp[5][4] = a[K][5];
for(int L = 1; L <= _cnt; L++)
{
if(a[L][1] != mp[1][1] || a[L][2] != mp[1][2] || a[L][3] != mp[1][3] || a[L][4] != mp[1][4] || a[L][5] != mp[1][5]) continue;
for(int M = 1; M <= _cnt; M++)
{
if(a[M][1] != mp[5][1] || a[M][2] != mp[5][2] || a[M][3] != mp[5][3] || a[M][4] != mp[5][4] || a[M][5] != mp[5][5]) continue;
getans();
}
}
}
}
}
}
}
}
}
}
}
}
}
/*----------------------------------------函数*/
int main()
{
n = read(); k = read(); prime();
dfs1(1, n, 0); _cnt--;
dfs2();
sort(ans + 1, ans + 1 + tot);
print();
return 0;
}
//写到吐