题解:CF1392E Omkar and Duck
首先,这种题有一种标准的处理逻辑,即通过拆位,通过每一位的值代表多种状态(一般为两种)。
先把最大值小于
这个很好办,我们给格点
但是,考虑到
对这
没啥思路,那让我们把图画出来看看:
我们这里把向下改为向上,实际上是等价的。此后,提到的“向上”也都代表题意中的“向下”
我们分别考虑每一步可能到达的点:
实际上,我们要区分的就是蓝线上相邻的两个点。并且不能和先前的值冲突。因此,我们考虑通过二进制一位的“
并且,我们发现,对于一条蓝线上的点,他们之间只需要相邻的两个点值不同,不相邻的点值相同没有影响。因为我们已经得到了当前位置,要推现在要向上还是向右,实际上只关注相邻点。因此,我们可以有如下构造:
对于点
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std ;
const int MAXN = 30 ;
int pow2[MAXN] ;
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0) ;
cout.tie(0) ;
int n ;
cin >> n ;
pow2[0] = 1 ;
for (int i = 1 ; i <= 2 * n ; i ++) {
pow2[i] = pow2[i - 1] * 2 ;
}
for (int i = 1 ; i <= n ; i ++) {
for (int j = 1 ; j <= n ; j ++) {
if (i % 2 == 1) {
cout << pow2[i + j - 2] << " " ;
}
else {
cout << 0 << " " ;
}
}
cout << endl ;
}
int q ;
cin >> q ;
while (q--) {
int cnt ;
cin >> cnt ;
int nowx = 1 , nowy = 1 ;
cout << 1 << " " << 1 << endl ;
for (int i = 1 ; i < 2 * n - 1 ; i ++) {
int p = cnt & (1ll << i) ;
int g = (nowx & 1) ^ (p != 0) ;
if (g == 0) {
nowy ++ ;
}
else {
nowx ++ ;
}
cout << nowx << " " << nowy << endl ;
}
}
return 0 ;
}