牛客练习赛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序列 (线性基)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FxCAD 实验三 实现对象的【属性】事
- 下一篇: 走台阶 OR 台阶走——《狂人C》习题解