DTZS-Round1-T5-数阵查询
解析
首先看到题目我们可以发现,或者应该要发现,变化次的 这个矩阵的规模是多大;
根据题意的变化规律:
- 当前有数字的方阵填充成 的大方阵:
- 在其方阵的右边界和下边界填上当前数阵没有的最小正整数。
不难发现,每多变化一次,规模是 的,所以显然可以得到递推式:
记 为 变化次的规模,初始条件 = 1
递推式:
然后思考什么情况下是无解的呢?
不难发现,当前给的是超出变化次的规模的,显然是无解的
直接输出;
那么对于有解的情况怎么思考呢?
有解的情况可以分为两类:
-
如果刚好处于当前变化的这一层的边界上,那么答案就是
也就是以下情况:

2.如果不处于当前变化的这一层的边界上
也就是以下情况的其中一种:

不难发现,我们其实都可以把 映射到 区域去,因为三个区域是由A区域变化过来的;
所以如果处于A区域,不需要变化;
如果不处于,直接做映射,然后发现,将映射到区域,其实就是找到变化次数 少一次的 对应的位置;
这个时候,我们就不难想到递归了,将当前转移传递到 上一层的 对应的节点的位置
设映射后的位置为
- 处于区域 ,
- 处于区域 ,
- 处于区域 ,
- 处于区域 ,
然后规模缩小一层,变成 大问题的子问题,直接递归即可
参考代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
ll b[45];
ll work(ll n , ll x , ll y){
if(x > b[n] || y > b[n]) return -1;
if(x == b[n] || y == b[n]) return n + 1;
ll x1 = x , y1 = y;
if(x > b[n-1]) x1 = x-b[n-1];
if(y > b[n-1]) y1 = y-b[n-1];
return work(n-1,x1,y1);
}
int main(){
b[0] = 1;
b[1] = 3;
for(int i = 2;i <= 20;i++){
b[i] = b[i-1] * 2 + 1;
}
int t;
cin >> t;
while(t--){
ll n,x,y;
cin >> n >> x >> y;
cout << work(n,x,y) << "\n";
}
return 0;
}
京公网安备11010802045784号