踩不出足迹(牛客练习赛88 )
题意:
长度为n的数组a,每个数是一个k位二进制
定义一下操作:
令第一次得到的结果为 a1a_1a1。你需要从第二个数开始,每次可以选择与上一次得到的结果异或或者同或起来。
问最大值是多少?
题集:
队友盲猜结论正确,orz
考虑异或和同或的性质,异或和同或都是具有交换律的,可以任意调换顺序。同或运算相当于和另一个数取反异或起来
所以有:a⊗¬b=¬a⊗b,¬a⊗¬b=a⊗ba⊗¬ b=¬a⊗ b,¬a ⊗¬b=a⊗ba⊗¬b=¬a⊗b,¬a⊗¬b=a⊗b
也就是如果我们有若干同或操作,其实就是将这个数取反再异或。那就是若干个数取反后异或起来。根据上面写的等式,两个取反排在一起可以消除这两个取反符号,那也就是最后有可能只剩一个取反,或者一个也没有。又因为交换律,我们将取反符号转移到最后一个数上。所以答案就是所有数异或和,或者前n-1个数异或,最后一个数同或
同或的操作就是与k位1异或,但是注意k<=64,如果直接1<<64再减1,ull也顶不住,可以通过1<<63+1<<63+1来实现
longlong范围:[−263,263−1][-2^{63},2^{63}-1][−263,263−1]
ull范围:[0,264−1][0,2^{64}-1][0,264−1]
代码:
// Problem: 踩不出足迹
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11178/C
// Memory Limit: 1048576 MB
// Time Limit: 2000 ms
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...);
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#elsestartTime= clock();freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn= 1e6 + 9;
ull a[maxn];
int main()
{//rd_test();int n, k;cin >> n >> k;for (int i= 1; i <= n; i++) {cin >> a[i];}ull num= 0;for (int i= 1; i <= n; i++) {num= num ^ a[i];}// cout << num << endl;ull ans= max(num, ((num) ^ ((1ull << (k-1)) + ((1ull << (k-1))-1ull))));cout << ans;//Time_test();
}