P10871 题解
非常有意思的一道题,这里提供一下我的构造方法。
点进来一看到样例吓一跳,这不直接猜棋子数是
先不细想正确性,考虑
小小手玩了一下,发现
我们改变之前从上往下放的思路,但是整体归纳分析的思路不能变,于是我们使用经典的从外到内放,发现外面的一圈对中间是没有影响的:每个棋子八个方向各有
所以我们只用考虑一圈怎么构造。接着我们开始手玩,这里我直接给出方法:
-
首先对于上边和下边,我们交替错开分别连着放两个棋子,容易证明这时符合要求。
-
接着对于左边和右边,我们也是交替错开分别连着放两个棋子,这时候由于上边和下边的皇后对于一个点刚好抵消,所以也是符合要求的。
这里一定要注意边界细节,可以参考代码的实现。
观察到我们此时昨晚上面两步后的形状大概是这样的:
111110
100001
100001
100001
100001
011110
但最后三个棋子无论怎样都放不进去,这时候我们做一步巧妙的步骤:往内层右上角先放一个。
我们发现它是能放进去的,并且放进去后,外层右上角也能放了,接着右下角,左下角都能放了。
这也带来一个问题,那就是我们往内层放了一个,打乱了节奏。这也很好解决,我们下一轮左右翻转一下就行了,毕竟我们本来第一个就是放角落的。
分析一下,除了最后到了
回过头看奇数,不也是这么做吗?
但同样的,到了
样例给出了
到这里,我们已经有了清晰的构造方案,奇数
但是当你信心满满的交上去,竟是 WA!
偷偷看一下错误信息,原来是偶数我们的答案大了 1。
接着又是手玩,可以在
1110 1110 1111 1111 1111 1111
1001 -> 1011 -> 1011 -> 1011 -> 1011 -> 1011
1001 1001 1001 1101 1101 1111
0110 0110 0110 0110 0111 0111
左右翻转的时候同理。
至此这道题就结束了。
#include<bits/stdc++.h>
//#include<Windows.h>
#define int long long
//#define ll long long
//#define double long double
#define fi first
#define se second
//#define ls t[p].l
//#define rs t[p].r
#define y1 yyyyyyyyyyyyyyyy1
using namespace std;
const int N = 4e3 + 10, inf = 1e9, M = 2e5;
//const double eps = 1e-16;
const int mod = 1e9 + 7;
//const int mod;
//const int AQX = 9;
mt19937 rnd(time(0) ^ clock());
int random(int l, int r){
return rnd() % (r - l + 1) + l;
}
const int offset = 101, offset2 = 103;
/*
_ _ _
____ _| |_ | |_ ___| |___ _ _
|_ / || | ' \ | ' \/ -_) / -_) ' \
/__|\_, |_||_|_|_||_\___|_\___|_||_|
|__/ |___|
*/
//struct Graph{
// int head[N], tot;
// struct edge{
// int t, f;
// int d, fa;
// int next;
// }e[N << 1];
// void edge_add(int u, int v, int w = 0){
// e[++tot].next = head[u];
// e[tot].t = v;
// e[tot].d = w;
// e[tot].f = u;
// head[u] = tot;
// }
// void clear(int n){
// for(int i = 1;i <= tot;i++)e[i].t = e[i].f = e[i].d = e[i].next = 0;
// for(int i = 1;i <= n;i++)head[i] = 0;
// tot = 0;
// }
//}g1, g2;
//int qmr(int x, int a){
// int ret = 1, p = x;
// while(a){
// if(a & 1)ret = ret * p % mod;
// p = p * p % mod;
// a >>= 1;
// }
// return ret;
//}
int n, vis[N][N];
vector<pair<int, int> >v;
void work(int nw, int f, int p){
if(nw == 2)return;
if(nw == 3){
if(f == 1){
v.push_back({p + 1, p + 2});
v.push_back({p + 1, p + 1});
v.push_back({p + 2, p});
v.push_back({p + 2, p + 2});
v.push_back({p + 2, p + 1});
v.push_back({p, p + 1});
v.push_back({p, p + 2});
v.push_back({p + 1, p});
}
else {
v.push_back({p + 1, p});
v.push_back({p + 1, p + 1});
v.push_back({p + 2, p + 2});
v.push_back({p + 2, p});
v.push_back({p + 2, p + 1});
v.push_back({p, p + 1});
v.push_back({p, p});
v.push_back({p + 1, p + 2});
}
return;
}
if(f == 1){
for(int i = p + 1, f = 0;i < nw + p - 1;i++, f ^= 1){
if(f)v.push_back({p, i}), v.push_back({p + nw - 1, i});
else v.push_back({p + nw - 1, i}), v.push_back({p, i});
}
for(int i = nw + p - 2, f = 0;i > p;i--, f ^= 1){
if(f)v.push_back({i, p}), v.push_back({i, p + nw - 1});
else v.push_back({i, p + nw - 1}), v.push_back({i, p});
}
if(nw == 4){
v.push_back({p + 1, n - p});
v.push_back({p, n - p + 1});
v.push_back({p + 2, n - p - 1});
v.push_back({p + 3, p + 3});
v.push_back({p + 2, p + 2});
}
else {
v.push_back({p + 1, n - p});
v.push_back({p, n - p + 1});
v.push_back({n - p + 1, n - p + 1});
v.push_back({n - p + 1, p});
work(nw - 2, 2, p + 1);
}
}
else {
for(int i = nw + p - 2, f = 0;i > p;i--, f ^= 1){
if(f)v.push_back({p, i}), v.push_back({p + nw - 1, i});
else v.push_back({p + nw - 1, i}), v.push_back({p, i});
}
for(int i = nw + p - 2, f = 1;i > p;i--, f ^= 1){
if(f)v.push_back({i, p}), v.push_back({i, p + nw - 1});
else v.push_back({i, p + nw - 1}), v.push_back({i, p});
}
if(nw == 4){
v.push_back({p + 1, p + 1});
v.push_back({p, p});
v.push_back({p + 2, p + 2});
v.push_back({p + 3, p});
v.push_back({p + 2, p + 1});
}
else {
v.push_back({p + 1, p + 1});
v.push_back({p, p});
v.push_back({n - p + 1, p});
v.push_back({n - p + 1, n - p + 1});
}
work(nw - 2, 1, p + 1);
}
}
signed main(){
cin >> n;
if(n <= 2){
cout << "1\n1 1\n" << endl;
return 0;
}
cout << n * n - 2 * (n % 2 == 0) << endl;
v.push_back({1, 1});
work(n, 1, 1);
for(auto x : v)printf("%lld %lld\n", x.fi, x.se);
return 0;
}
/*
2 3
3 1
2 2
1 1
3 3
3 2
1 2
1 3
2 1
*/