2019牛客国庆集训派对day4 C Intersection (线性基的交-容斥/高斯消元)

题目链接:https://ac.nowcoder.com/acm/contest/1109/C
注意线性基的交不能简单的查询是否相关,并是可以直接并的,大部分人采用的是直接容斥的做法,其实是有基的交的算法的,贴在下面。标程好像是用的高斯消元求秩(然而蒟蒻不会)。

struct L_B{
    ll base[maxbit];
 
    void clear(){
        memset(base,0,sizeof(base));
    }
 
    void ins(ll number){
        for(int j = maxbit-1; j >= 0; j--) if(number>>j) {
            if(!base[j]){
                base[j] = number;
                return;
            }
            else{
                number ^= base[j];
            }
        }
        return;
    }
 
    void intersect(L_B A, L_B B){
        L_B C=B,D=B;
        for(int i = 0; i < maxbit; i++){
            ll x = A.base[i];
            if(!x) continue;
            int j = i;ll T = 0;
            for(; j >= 0; j--) if(x>>j) {
                if(C.base[j]){
                    x ^= C.base[j];
                    T ^= D.base[j];
                } else break;
            }
            if(!x) base[i] = T;
            else {
                C.base[j] = x;
                D.base[j] = T;
            }
        }
    }
 
    bool check(ll number){
        for(int i = maxbit-1; i >= 0; i--) if(number>>i) {
            if(!base[i]) return false;
            number ^= base[i];
        }
        return true;
    }
 
};

代码:

#include
using namespace std;
#define maxn 105
#define maxm 1006
#define ll long long int
#define INF 0x3f3f3f3f
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
#define mem(a) memset(a,0,sizeof(a))
#define sqr(x) (x*x)
#define inf (ll)2e18+1
#define PI acos(-1)
#define mod 1000000007
#define auto(i,x) for(int i=head[x];i;i=ed[i].nxt)
ll read(){
    ll x=0,f=1ll;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
     return f*x;
}
int n,B=61;
ll a[100],b[100],c[maxn],d[maxn];
void insert(ll P[],ll x) {
    for(int i = B; i >= 0; i--) {
        if((1ll<<i)&x) {
            if(!P[i]) {P[i] = x; break;}
            x ^= P[i];
        }
    }
}
int Query(ll P[],ll x) {
    for(int i = B; i >= 0; i--) {
        if((x >> i) & 1) {
            if(!P[i]) return 0;
            x ^= P[i];
        }
    }
    if(x == 0) return 1;
    else return 0;
}
int main()
{
    //printf("%lld\n",(1ll<
    while(~scanf("%d",&n)){
        ll x;
        inc(i,1,n)c[i]=read();
        sort(c+1,c+n+1);
        int len1=unique(c+1,c+n+1)-c-1;
        inc(i,1,len1)insert(a,c[i]);
        int cnt=0;
        ll ans=0;
        inc(i,0,60)if(a[i])cnt++;
        ans+=1ll<<cnt;
        cnt=0;
        inc(i,1,n)d[i]=read();
        sort(d+1,d+n+1);
        int len2=unique(d+1,d+n+1)-d-1;
        inc(i,1,len2)insert(b,d[i]);
        inc(i,0,60)if(b[i])cnt++;
        ans+=1ll<<cnt;
        cnt=0;
        inc(i,0,60)if(b[i])insert(a,b[i]);
        inc(i,0,60)if(a[i])cnt++;
        ans-=1ll<<cnt;
        mem(a);mem(b);cnt=0;
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(数学-线性基)