cf #633 (Div. 2) E. Perfect Triples 打表找规律

我们跑个暴力的dfs 把三元组按顺序找出来  然后找规律(很多时候打了表我也不知道有啥规律)

因为是异或操作 我们可以看二进制表   但是看四进制表可能更可以看出这个规律

1行(第一块)

001 002 003 

4行(第二块)

010 020 030

011 022 033

012 023 031

013 021 032

16行(第三块)

100 200 300

101 202 303

102 203 301

103 201 302

110 220 330

111 222 333

112 223 331

113 221 332

120 230 330

。。。。。。。。

我们发现每一块(位数一样的我们视为一块)的行数分别是 1 4 16 64。。。。 那我们可以先找出询问的位置在哪一块 还可以找到它在哪一列    

然后我们一个块一个块的看   我们发现第i块有i位四进制

最高位等于列数  第二高位似乎没什么规律 

在第二块 我们发现 第一列的第二高位 是0 1 2 3  第二列是 0 2 3 1 第三列是 0 3 1 2  

然后我们看第三块  第二高位的规律似乎变了  但是我们看最低位 第一列 是0 1 2 3 循环  第二列是 0 2 3 1循环 第三列是 0 3 1 2 循环  第一列的第二高位似乎是 4个0 4个1 4个2 4个3 循环  第二列和第三列也类似 这时候我们可以往后面再打几行 或者猜一个规律

这个规律就是  第一列的数 在最低位 是 0 1 2 3 循环  第二位是 4*(0 1 2 3) 循环 第三位是 16*(0 1 2 3) 循环以此类推 

最高位保持和列数相同 

第二列和第三列  分别是 0 2 3 1和 0 3 1 2 这样的循环方式 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p4[33];
ll g[4][5];
int main(){
	int t;
	p4[0]=1;
	g[1][0]=0,g[1][1]=1,g[1][2]=2,g[1][3]=3;
	g[2][0]=0,g[2][1]=2,g[2][2]=3,g[2][3]=1;
	g[3][0]=0,g[3][1]=3,g[3][2]=1,g[3][3]=2;
	for(int i = 1; i <= 30; i++) p4[i]=p4[i-1]*4;
	scanf("%d",&t);
	while(t--){
		ll n;
		scanf("%lld",&n);
		ll p = n/3+1,c = n%3;
		if(!c) c=3,p--;
		ll ct = 1,now = 1;
		while(p>now){
			p-=now;
			ct++;
			now*=4ll;
		}
		//printf("p=%lld c=%lld ct=%lld now=%lld\n",p,c,ct,now);
		ll ans = 0;
		p--;
		ans+=c*p4[ct-1];
		for(ll i = ct-1; i >= 1; i--){
			ans+=g[c][(p/p4[i-1])%4]*p4[i-1];
		}
		printf("%lld\n",ans);
	}
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值