欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

牛客练习赛26 Dxor序列 (线性基)

发布时间:2023/12/18 编程问答 40 豆豆
生活随笔 收集整理的这篇文章主要介绍了 牛客练习赛26 Dxor序列 (线性基) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

链接:https://ac.nowcoder.com/acm/contest/180/D
来源:牛客网

xor序列
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小a有n个数,他提出了一个很有意思的问题:他想知道对于任意的x, y,能否将x与这n个数中的任意多个数异或任意多次后变为y

输入描述:
第一行为一个整数n,表示元素个数
第二行一行包含n个整数,分别代表序列中的元素
第三行为一个整数Q,表示询问次数
接下来Q行,每行两个数x,y,含义如题所示
输出描述:
输出Q行,若x可以变换为y,输出“YES”,否则输出“NO”
示例1
输入
复制
5
1 2 3 4 5
3
6 7
2 1
3 8
输出
复制
YES
YES
NO
说明
对于(6,7)来说,6可以先和3异或,再和2异或
对于(2,1)来说,2可以和3异或
对于(3,8)来说,3不论如何都不能变换为8
备注:
对于100%的数据,n,Q<=105
保证所有运算均在int范围内

题意:

思路:

异或的性质:

y^y=0 则 x^y^y=x

令 x^z=y 两边异或x , 则 x^z^x=y^x -> z= y^x

即在数组中 找出一些数异或起来等于z即可。

这恰好是线性基的基础功能。

细节见代码:

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;} inline void getInt(int* p); const int maxn=1000010; const int inf=0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/struct LB {// 注意最高是60还是62ll d[61], p[61];int cnt, mx;LB() {memset(d, 0, sizeof(d));memset(p, 0, sizeof(p));cnt = 0, mx = 61;}void init() {memset(d, 0, sizeof(d));memset(p, 0, sizeof(p));}bool add(ll val) {/*插入时判断之前是否有数会与val异或得0,判第k小时如果有为0的情况,k要减一*/for (int i = mx - 1; i >= 0; i--) {if (val & (1LL << i)) {if (!d[i]) {d[i] = val; break;}val ^= d[i];}}return val > 0;}bool query(ll val) { // 查询val这个数是否存在for (int i = mx - 1; i >= 0; i--) {if (val & (1LL << i)) {if (!d[i]) return 0;val ^= d[i];}}return 1;}ll query_max(ll val) {ll ret = val;for (int i = mx - 1; i >= 0; i--) if ((ret ^ d[i]) > ret) ret ^= d[i];return ret;}ll query_min() {for (int i = 0; i < mx; i++) if (d[i]) return d[i];return 0;}void rebuild() {//消元,保存到p数组cnt = 0;for (int i = 0; i < mx; i++) {for (int j = 0; j < i; j ++ )if (d[i] & (1LL << j)) d[i] ^= d[j];}for (int i = 0; i < mx; i++) if (d[i]) p[cnt++] = d[i];}ll query_kth(ll k) { //使用前需要rebuildll ret = 0;if (k >= (1LL << cnt)) return -1;for (int i = cnt - 1; i >= 0; i--) if (k & (1LL << i)) ret ^= p[i];return ret;}ll find(ll x) { //找x是第几大的数,需保证x一定在ll ret = 0, c = 0;for (int i = 0; i < mx; i++) {if (d[i]) {if (x >> i & 1) ret += (1LL << c);c++;}}return ret;}LB operator+(const LB & _A)const { //合并LB ret = *this;for (int i = mx - 1; i >= 0; i--) if (_A.d[i]) ret.add(_A.d[i]);return ret;} }; LB base=LB();int main() {//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);int q;int n,x;cin>>n;repd(i,1,n){cin>>x;base.add(x);}cin>>q;int y;while(q--){cin>>x>>y;x^=y;if(base.query(x)){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}}return 0; }inline void getInt(int* p) {char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}}else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}} }

转载于:https://www.cnblogs.com/qieqiemin/p/11249973.html

总结

以上是生活随笔为你收集整理的牛客练习赛26 Dxor序列 (线性基)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。