Acwing_98

题目链接

考察知识点: 坐标变换、递归、分治。


核心问题:计算出点的坐标。

策略是递归算出子图形中的坐标,再进行平移得到当前图形中的坐标。

采用下图方式建立坐标系:原点在中心。

在这里插入图片描述

前置知识:

( x , y ) (x,y) (x,y) 逆时针旋转 θ \theta θ 角度,坐标为 ( x cos ⁡ θ − y sin ⁡ θ , x sin ⁡ θ − y cos ⁡ θ ) (x\cos\theta-y\sin\theta,x\sin\theta-y\cos\theta) (xcosθysinθ,xsinθycosθ)

n n n 为等级, m m m 为在等级为 n n n 时的编号。

单 位 长 度 = 2 n 单位长度=2^{n} =2n

l e n = 单 位 长 度 2 = 2 n − 1 len = \frac{单位长度}{2} = 2^{n-1} len=2=2n1

m = 4 n = 2 2 n m=4^{n}=2^{2n} m=4n=22n

等级 2 2 2 0 0 0 号图形是由等级 1 1 1 的图形顺时针旋转 90 ° 90° 90° ,再进行 y y y 轴轴对称得到。

假设在等级 1 1 1 中的坐标为 ( x , y ) (x,y) (x,y) ,旋转后为 ( y , − x ) (y,-x) (y,x) ,再进行关于 y y y 轴的轴对称得到 ( − y , − x ) (-y,-x) (y,x)

同理可以得到如下表格:

原始坐标图形0中坐标图形1中坐标图形2中坐标图形3中坐标
( x , y ) (x,y) (x,y) ( − y , − x ) (-y,-x) (y,x) ( x , y ) (x,y) (x,y) ( x , y ) (x,y) (x,y) ( y , x ) (y,x) (y,x)

因为等级 1 1 1 的原点和等级 2 2 2 的原点不重合,所以需要将原点进行平移。

原点平移后得到最终坐标如下:

原始坐标图形0图形1图形2图形3
$(x,y) $ ( − y − l e n , − x + l e n ) (-y-len,-x+len) (ylen,x+len) ( x + l e n , y + l e n ) (x+len,y+len) (x+len,y+len) ( x + l e n , y − l e n ) (x+len,y-len) (x+len,ylen) ( y − l e n , x − l e n ) (y-len,x-len) (ylen,xlen)

我们的编号从 0 0 0 开始,计算坐标注意减一。

时间复杂度: O ( n ) O(n) O(n)

代码
// #pragma GCC optimize(3)
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <deque>
#include <cctype>
#include <string>
#include <cstdio>
#include <bitset>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
// #include <unordered_set>
// #include <unordered_map>
#define endl '\n'
#define x first
#define y second
#define fi first
#define se second
#define PI acos(-1)
// #define PI 3.1415926
#define LL long long
#define INF 0x3f3f3f3f
#define lowbit(x) (-x&x)
#define ULL unsigned LL
#define PLL pair<LL, LL>
#define PIL pair<int, LL>
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define mem(a, b) memset(a, b, sizeof a)
#define rev(x) reverse(x.begin(), x.end())
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

using namespace std;

LL n, a, b;

PLL calc(LL n, LL m) {
	if (n == 0) return {0, 0};
	LL len = 1ll << (n - 1), cnt = 1ll << (2 * n - 2);
	PLL pos = calc(n - 1, m % cnt);
	LL x = pos.x, y = pos.y;
	int z = m / cnt;
	if (z == 0) {
		return {-y - len, -x + len};
	} else if (z == 1) {
		return {x + len, y + len};
	} else if (z == 2) {
		return {x + len, y - len};
	} 
	return {y - len, x - len};
}

void solve() {
	int tt;
    cin >> tt;
    while (tt -- ) {
    	cin >> n >> a >> b;
    	PLL ac = calc(n, a - 1), bc = calc(n, b - 1);
    	double dx = ac.x - bc.x, dy = ac.y - bc.y;    	
    	printf("%.0lf\n", sqrt(dx * dx + dy * dy) * 5);
    }
}

int main() {
	IOS;
	
	solve();
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值