• 《算法竞赛进阶指南》0x35高斯消元与线性空间 异或空间


    题目链接:https://www.acwing.com/problem/content/212/

    给定n个数,要求这些数能够异或的数中的第k小,通过求异或线性基就可以得到这些数可以异或得到的不相同的数的维数,通过这些线性基的异或便可以得到这些数的异或的所有可能的数,

    异或基中从大到小的数的最高位为1,其他数的这一位一定不是一,所以假设异或基的维数是4,则从大到小的数分别是第1000、0100、0010、0001小的数,所以只要将询问按照二进制进行分解就可以

    ,如果k的第i位是1,则取基中第dim-i个数异或到结果中去。

    注意到我们的异或基都是非零的,所以如果从给的数里面能够得到0的话,第k大就相当于基构成的数中的第k-1大,如果不能得到0的话,就从我们的基中取第k小的,就可以。

    还有一个注意点就是数据的范围,需要用unsigned long long 来进行存储,在scanf中使用的是%llu.

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define maxn 10010
    unsigned long long a[maxn];
    int main(){
        int T,n;
        cin>>T;
        int dim;
        for(int kase=1;kase<=T;kase++){
            scanf("%d",&n);
            for(int i=1;i<=n;i++)scanf("%llu",&a[i]);
            bool zero=0;//检查若干个数的异或是否可能是0 
            dim = n;//异或空间的基的维数 
            for(int i=1;i<=n;i++){//最多循环64次,基的维数便确定 
                for(int j=i+1;j<=n;j++){
                    if(a[j]>a[i])swap(a[i],a[j]);
                }
                if(a[i]==0){
                    dim=i-1;
                    zero=true;
                    break;
                }
                for(int j=63;j>=0;j--){
                    if(a[i]>>j & 1){ 
                        for(int k=1;k<=n;k++){
                            if(i!=k && (a[k]>>j & 1))a[k]^=a[i];
                        }
                        break;
                    }
                } 
            }
            
    //         cout<<dim<<endl;
            int m;
            cin>>m;
            printf("Case #%d:
    ",kase); 
            while(m--){
                unsigned long long  k,ans=0;
                scanf("%llu",&k);   
                if(zero)k--;//从这些数里面可以拼出0 
                if(k >= ((unsigned long long )1<<dim))puts("-1");
                else{
                    for(int i=dim-1;i>=0;i--){
                        if(k>>i & 1)ans^=a[dim-i];
                    }
                    printf("%llu
    ",ans);
                }
            } 
        } 
    }
  • 相关阅读:
    执行超过1个小时的SQL语句
    非周一回写销售预测
    openLDAP
    Windows下使用性能监视器监控SqlServer的常见指标
    ORA-01720: grant option does not exist for 'xxx.xxxx' (ORA-01720 ‘XXX’ 不存在授权选项)
    117 FP页面无法查看 此错误是JDK8.0.0.0版本的一个BUG,会导致工单重复回写,
    KPI
    Quatrz + Spring
    windows 脚本
    Spring集成Redis
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13265979.html
Copyright © 2020-2023  润新知