P5514 [MtOI2019]永夜的报应【题解】

这是一道简单的数论(贪心)题

题目大意:

  • 对于非负整数数列:
    a 1 , a 2 , a 3 . . . . . . a n a_1,a_2,a_3......a_n a1,a2,a3......an
    将其划分为 M M M组,使其异或和最小。

解题思路:

我们考虑一对二进制数 a = ( 10011 ) 2 a=(10011)_2 a=(10011)2 b = ( 11001 ) 2 b=(11001)_2 b=(11001)2.异或运算的性质为:
1   x o r   1 = 0 1\space xor \space 1=0 1 xor 1=0 0   x o r   0 = 0 0\space xor \space 0=0 0 xor 0=0 1   x o r   0 = 1 1\space xor \space 0=1 1 xor 0=1 0   x o r   1 = 1 0 \space xor \space 1=1 0 xor 1=1
若我们将 a a a b b b 求异或,得到:
a n s 1 = a   x o r   b = ( 01110 ) 2 ans_1=a \space xor \space b=(01110)_2 ans1=a xor b=(01110)2
而若我们将其合成同一组则:
a n s 2 = a + b = ( 101100 ) 2 ans_2=a+b=(101100)_2 ans2=a+b=(101100)2
显然有
a n s 1 < a n s 2 ans_1< ans_2 ans1<ans2
实际上,根据异或的运算规律,有:
∀ a , b ∈ R ∗ , a   x o r   b ≤ a + b \forall a,b\in\mathbb R^*,a\space xor \space b\leq a+b a,bR,a xor ba+b
所以我们根本就不用分组,全部异或起来就好啦!

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
	int n;
	int x;
	cin>>n;
	cin>>x;
	for(int i=1;i<n;i++)
	{
    
    
		int y;
		cin>>y;
		x^=y;
	}
	cout<<x<<endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_62444770/article/details/120585161