*题解:CF1392E Omkar and Duck
解析
考虑二进制拆分。直接令每个位置代表二进制的每个不同位显然不可行,不过可以注意到对于 \(x + y\) 相等的格子组成的斜线,每条斜线到达且仅到达一次,所以不妨按照斜线来分配二进制位。然而这样我们无法区分路径,考虑目前已经在某个格子上了,如何区分向下走和向右走,显然即将走到的两个格子的 \(x + y\) 相等,也就是位于同一条斜线上。不妨将格子上的值一个设为 \(2^{x + y - 2}\),一个设为 \(0\),可以钦定偶数行设为 \(0\)。这样对于给定的一个路径权值和 \(k\),只需从低位往高位遍历,判断当前格子取值与下一个格子取值是否都为 \(0\) 或都不为 \(0\) 即可。
时间复杂度 \(O(qn)\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 25 + 5,mod = 1e9 + 7;
typedef long long ll;
ll mp[N][N];
void god(int &x,int &y){
x++;
cout<<x<<" "<<y<<endl;
}
void gor(int &x,int &y){
y++;
cout<<x<<" "<<y<<endl;
}
int main(){
// ios::sync_with_stdio(false);
// cin.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mp[i][j] = ((i & 1) ? (1ll << (i + j - 2)) : 0);
cout<<mp[i][j]<<" ";
}
cout<<endl;
}
int q;
cin>>q;
while(q--){
ll k;
cin>>k;
cout<<1<<" "<<1<<endl;
int x = 1,y = 1;
for(int i=1;i<=n + n - 2;i++){
bool f = mp[x][y] == 0;
if(f == bool(k & (1ll << i))){
god(x,y);
}else{
gor(x,y);
}
}
}
return 0;
}

浙公网安备 33010602011771号