Codeforces Round 931 (Div. 2)

Problem - D1 - Codeforces

异或题

目录

题意:

思路:

性质1:

性质2:本题核心

性质3:关于n的首位被异或

于是分类讨论:

1.首位相同

2.首位不同且n只多一个前位1

3.首位不同且多前位1

参考代码:


题意:

给你 n , m,让你对 n 做异或(^)操作,使其变为 m 。

但是你对 n 异或的数 y 得满足两个条件:

  1. 0 < y < n

  2. 0 < y^n < n

思路:

异或很烦,两个条件更烦。

对条件进行探究得出一些规律后,分类讨论。

性质1:

比如

n = 1101

m = 0001

我们可以把n的1变成0

因为n的任意一个二进制位都是小于n的,而对1异或会使这一位变成0,即异或的结果是变小的

满足条件1,2。

性质2:本题核心

(这个我当时想到了,但是没有接着向后系统地分析)

n = 11000

m = 00010

我们可以让n异或01111,符合条件1、2,

所以n = 10111,接着用性质1即可得到m。

这种操作牺牲一个前位1使其后面全为1

(前位就是前面位置的意思,为了方便略写)

性质3:关于n的首位被异或

  1. 结果为0

结果肯定小于n,但这个数得小于n哦。

  1. 结果为1

这个数肯定小于n,但是结果可能大

于是分类讨论:

(n > m 这种条件就不多说了吧)

1.首位相同

n = 1010

m = 1001

可以直接得到,n 异或上 0011

(性质3,0始的异或值肯定小,而异或结果m本来就小于n,满足条件1、2)

2.首位不同且n只多一个前位1

n = 10

m = 01

n = 1001

m = 0010

这种的就没有结果,不满足条件1、2。

3.首位不同且多前位1

n = 1100

m = 0010

用性质2随便转了,先转成牺牲一个前位1使其后面全为1的,然后就能用性质1直接转为m

当n的第二个1和m的第一个1同一位时:

n = 1010101

m = 0011001

这个没法性质2,但对n异或1001101可以直接得到m,类似情况1了。

参考代码:

复制代码
#define ll long long
#define endl "\n"
#define int long long
const ll inf = 1e9;
const ll MOD = 998244353;

void solve()
{
	int n, m;
	cin >> n >> m;
	//2的10次方是3颗0
	//   60      18
	int cnt1 = 0, cnt2 = 0;
	int i;
	for (i = 62; i >= 0; i--)
	{
		if (n & (1ll << i))cnt1++;
		if (m & (1ll << i))
		{
			cnt2++; break;
		}
	}
	vector<int>ret;
	if (cnt1 == cnt2)
	{
		if (n & (1ll << i))//首位相同
		{
			ret.push_back(n);
			ret.push_back(m);
		}
		else
		{
			cout << -1 << endl;
			return;
		}
	}
	else
	{
		if (cnt1 > cnt2 + 1||!(n & (1ll << i)))
		{
			ret.push_back(n);
			int k = -1;
			for (int j = 62; j >= 0; j--)
			{
				if ((n & (1ll << j)))
				{
					if (k == -1)
						k = 0;
					else
					{
						k = j; break;
					}
				}
			}

			int tmp = 0;
			for (int j = 0; j <= k; j++)
			{
				tmp |= (1ll << j);
			}
			ret.push_back(tmp);
			if(tmp!=m)///
				ret.push_back(m);
		}
		else
		{
			ret.push_back(n);
			ret.push_back(m);
		}
	}

	//
	cout << ret.size()-1 << endl;
	for (int x : ret)
	{
		cout << x << " ";
	}
	cout << endl;
}
signed main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}
相关推荐
茉莉玫瑰花茶9 分钟前
C++ 17 详细特性解析(4)
开发语言·c++·算法
long31623 分钟前
K‘ 未排序数组中的最小/最大元素 |期望线性时间
java·算法·排序算法·springboot·sorting algorithm
进击的小头27 分钟前
FIR滤波器实战:音频信号降噪
c语言·python·算法·音视频
xqqxqxxq31 分钟前
洛谷算法1-1 模拟与高精度(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
razelan31 分钟前
初级算法技巧 4
算法
砍树+c+v32 分钟前
3a 感知机训练过程示例(手算拆解,代码实现)
人工智能·算法·机器学习
zy_destiny33 分钟前
【工业场景】用YOLOv26实现4种输电线隐患检测
人工智能·深度学习·算法·yolo·机器学习·计算机视觉·输电线隐患识别
智驱力人工智能43 分钟前
货车违规变道检测 高速公路安全治理的工程实践 货车变道检测 高速公路货车违规变道抓拍系统 城市快速路货车压实线识别方案
人工智能·opencv·算法·安全·yolo·目标检测·边缘计算
罗湖老棍子1 小时前
【例9.18】合并石子(信息学奥赛一本通- P1274)从暴搜到区间 DP:石子合并的四种写法
算法·动态规划·区间dp·区间动态规划
2301_810730101 小时前
python第四次作业
数据结构·python·算法