• HDU 3949:XOR(高斯消元+线性基)


    题目链接

    题意

    给出n个数,问这些数的某些数xor后第k小的是谁。

    思路

    高斯消元求线性基。

    学习地址

    把每个数都拆成二进制,然后进行高斯消元,如果这个数字这一位(列)有1,那么让其他数都去异或它,消掉这一列的1,使得最后得到的矩阵某一行如果那一列有1的话,那么其他行是不会有1的(就是线性基)。

    最后得到一个行数row,代表总共有row个1。

    这个证明还没想通,直接用了。

    如果得到的row == n的话,代表每一个数都有一个1,那么是取不到0的,这个时候只能得到 2^row - 1 个数,否则其他时候都可以取0。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int INF = 0x3f3f3f3f;
    const int N = 1e4 + 11;
    LL a[N];
    
    int Gauss(int n) {
    	int row = 1;
    	for(int k = 63; k >= 0; k--) {
    		for(int i = row; i <= n; i++) {
    			if((a[i] >> k) & 1) {
    				swap(a[i], a[row]);
    				for(int j = 1; j <= n; j++)
    					if(j != row && ((a[j] >> k) & 1))
                            a[j] ^= a[row];
    				row++;
    				break;
    			}
    		}
    	}
    	return row - 1;
    }
    
    LL solve(int row, int n, LL k) {
        if(row < n) {
            if(k == 1) return 0;
            k--;
        }
    	if((1LL << row) <= k) return -1;
    	LL ans = 0;
    	for(int i = 63; i >= 0; i--)
    		if((k >> i) & 1) ans ^= a[row-i];
    	return ans;
    }
    
    int main() {
    	int t; scanf("%d", &t);
    	for(int cas = 1; cas <= t; cas++) {
    		int n; scanf("%d", &n);
    		for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    		int row = Gauss(n);
    		int q; scanf("%d", &q);
    		printf("Case #%d:
    ", cas);
    		while(q--) {
    			LL k; scanf("%lld", &k);
    			printf("%lld
    ", solve(row, n, k));
    		}
    	} return 0;
    }
    
  • 相关阅读:
    Office2010中功能强大的图片背景删除工具
    ArcGIS 缓冲区单位转换问题
    ArcGIS Server 优化
    SQLSERVER 三值逻辑
    SQLSERVER 重置自增列
    ArcGIS 基于AO 实现的经纬度定位
    AO连接ArcGIS server 超时问题
    MySQL 1064 错误
    Socket 请求http 汉字编码问题
    Navicat创建存储过程
  • 原文地址:https://www.cnblogs.com/fightfordream/p/7649167.html
Copyright © 2020-2023  润新知