*题解: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;
}

posted @ 2026-08-15 14:47  yutar  阅读(5)  评论(0)    收藏  举报