• Moscow Pre-Finals Workshop 2020


    Moscow Pre-Finals Workshop 2020 - Legilimens+Coffee Chicken Contest A. Everyone Loves Playing Games

    题意

    Alice和Bob玩游戏,两人分别有(n)对数和(m)对数((x_i,y_i))

    初始分数(X = 0)

    操作可以选择数对中的一个数,最终把这些数异或起来构成最终分数,Alice希望(X)尽量大,Bob希望(X)

    Alice会先用完所有操作,然后Bob再用所有操作,两人都知道对方的数对

    [1 leq N,M leq 10000\ 1 leq x_i,y_i leq 10^{18} ]

    分析

    考虑先简化问题,两个数中选择一个数,可以先假定选择所有的(x_i),并将(x_i oplus y_i)代替(x_i,y_i) 插入原序列,这样相当于对于序列中的数选还是不选的问题

    对于集合中的数可以任意选择,我们可以考虑使用线性基,线性基大概就是说 我们可以找到一些基,这些基能够张成出原有数能张成的所有数

    这样就把规模压缩到了(O(logn)) ,下面考虑两人的策略

    对于每一位分别考虑,局面可以归纳为三元组(X当前位是否为1,Alice当前为是否有1,Bob当前位是否有1)

    对于((x,0,0)) 两人都无法操作,对于((1,0,1)) ,Bob一定会操作,对于((0,1,0))Alice一定会操作

    对于((1,1,1))若Alice操作,Bob就不会操作,若Alice不操作,Bob就会操作,((0,1,1))同理,这个时候可以再用类似上面的方法,先操作并插入他们的异或,如不更优,可以反悔

    代码

    #include<bits/stdc++.h>
    using namespace std;
     
    typedef long long ll;
    typedef vector<ll> VI;
    const int maxn=20005,MAX_BASE=60;
     
    struct Linear_Bases {
    	ll b[MAX_BASE+5];
    	Linear_Bases() {
    		fill(b,b+MAX_BASE+1,0);
    	}
    	void clear(){
    		fill(b,b+MAX_BASE+1,0);
    	}
    	void add(ll num) {
    		for(int j=MAX_BASE; j>=0; j--)
    			if(num>>j&1) {
    				if(b[j]) { //该位存在基
    					num^=b[j];
    					continue;
    				}
    				b[j]=num;
    				for(int k=j-1; k>=0; k--)if(b[j]>>k&1)b[j]^=b[k];
    				for(int k=j+1; k<=MAX_BASE; k++)if(b[k]>>j&1)b[k]^=b[j];
    				break;
    			}
    	}
    	void build(vector<int>a) {
    		for(int num:a)add(num);
    	}
    }A,B;
     
    inline ll rd(){
        ll x;
        scanf("%lld",&x);
        return x;
    }
     
    int main(){
        int T = rd();
        while(T--){
            int n = rd();
            int m = rd();
    		A.clear();
    		B.clear();
    		ll xors = 0;
            for(int i = 0;i < n;i++){
                ll a = rd();
                ll b = rd();
                xors ^= a;
                A.add(a ^ b);
            }
            for(int i = 0;i < m;i++){
                ll a = rd();
                ll b = rd();
                xors ^= a;
                B.add(a ^ b);
            }
            for(ll now = 1ll << 61,i = 61;i >= 0;now >>= 1,i--){
                if(xors & now) {
                    if(A.b[i]) {
                        if(B.b[i]) {
                            xors ^= A.b[i];
                            A.add(A.b[i] ^ B.b[i]);
                        }
                    }
                    else if(B.b[i]) xors ^= B.b[i];
                }
                else{
                    if(A.b[i]) {
                        if(B.b[i]) {
                            A.add(A.b[i] ^ B.b[i]);
                        }
                        else xors ^= A.b[i];
                    }
                }
            }
            printf("%lld
    ",xors);
        }
    }
    
  • 相关阅读:
    sql左外连接、右外连接、group by、distinct(区别)、intersect(交叉)、通配符、having
    nvarchar,varchar 区别
    链家笔试链家——找寻最小消费获取最大平均分java
    利用SpringAOP 实现 日志输出
    AOP 学习笔记
    Spring AOP中pointcut expression表达式解析
    基于@Aspect的AOP配置
    URI 中特殊字符处理
    给电脑设置视力保护色
    Spring不支持依赖注入static静态变量
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15368116.html
Copyright © 2020-2023  润新知