Hetao P10483 [XRCOI Round 4] 异或 题解 [ 黄 ] [ 进制 ] [ 差分 ]

异或:蒟蒻的第三道公开赛题 qwq。

#1~4

\(p\) 转化为十进制数,然后暴力求每次操作的数,直接模拟即可。

#5~8

正解的弱化版,是留给将十六进制转二进制实现较劣或者暴力区间修改的,时间复杂度是 \(O(n^2)\) 的,具体见后文。

#9~12

观察该性质有何意义,把 \(a=b+1\) 带入函数中,得 \(G(b+1,b)=2^{b+1}-2^{b}=2^b\),也就是说,我们每次操作将 \(p\)\(2^b\) 异或。

既然是与 \(2\) 的整数次幂异或,并且异或是在二进制下进行的,因此我们要先将十六进制数转化为二进制数。

由于十六进制数的每位数小于 \(16=2^4\),所以我们可以把十六进制数中的每一位数转化为一个位数为 \(4\) 的二进制数来表示。具体的实现上,可以通过 map 储存每一个字母转换为 \(4\) 位二进制数后对应什么,然后重新求出二进制数即可。

那么对于二进制数和 \(2^b\) 异或是容易的,直接将二进制数的第 \(b\) 位取反即可。

#13~20

继续观察这个函数有什么意义,不难发现:

\[G(a,b)=2^a-2^b=2^{a-1}+2^{a-1}+2^b=2^{a-1}+2^{a-2}+2^{a-2}+2^b = \dots = 2^{a-1}+2^{a-2}+\dots+2^{b+1}+2^b \]

因此,我们需要将原二进制数中的第 \(b\sim a-1\) 位全部取反,这个显然可以用差分实现。时间复杂度为 \(O(n)\)

代码如下:

#include <bits/stdc++.h>
using namespace std;
int n,a,b;
string s,res;
unordered_map<int,char>ist={{0,'0'},{1,'1'},{2,'2'},{3,'3'},{4,'4'},{5,'5'},{6,'6'},{7,'7'},{8,'8'},{9,'9'},{10,'A'},{11,'B'},{12,'C'},{13,'D'},{14,'E'},{15,'F'}};
unordered_map<char,int>mp={{'0',0},{'1',1},{'2',2},{'3',3},{'4',4},{'5',5},{'6',6},{'7',7},{'8',8},{'9',9},{'A',10},{'B',11},{'C',12},{'D',13},{'E',14},{'F',15}};
bitset<800005>ori,f,ans;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);	
	cin>>s;
	for(int i=0,k=s.length()-1;i<s.length();i++,k--)
	{
		int tmp=mp[s[k]];
		for(int j=i*4;j<=i*4+3;j++)
		{
			ori[j]=(tmp&1);
			tmp>>=1;
		}
	}
	cin>>n;
	while(n--)
	{
		cin>>a>>b;
		f[a]=(f[a]^1);
		f[b]=(f[b]^1);
	}
	for(int i=1;i<s.length()*4;i++)f[i]=(f[i]^f[i-1]);
	ans=(ori^f);
	for(int i=0;i<s.length();i++)
	{
		int tmp=0,tms=1;
		for(int j=i*4;j<=i*4+3;j++)
		{
			tmp+=tms*ans[j];
			tms*=2;
		}
		res+=ist[tmp];
	}
	for(int i=res.length()-1,legal=0;i>=0;i--)
	{
		if(res[i]!='0')legal=1;
		if(legal)cout<<res[i];
	}
	return 0;
}

感觉这题就是涉及到一个进制的转化,以及一个简单结论在二进制下的表现,还是比较简单的。

posted @ 2025-08-11 00:16  KS_Fszha  阅读(30)  评论(0)    收藏  举报