• 2019.01.15-jzoj-子序列&&dtoj-4114-sub


    题目描述:

    他得到了一个长度为 n 的数组 a1,a2,a3,...,an,他想知道 xor 值为 0 的子 序列最长是多少。

    标签:线性基,FWT

    思路:

    我们要找异或值为0的,可以反过来寻找异或值为整个数组异或值的数。我们知道一个序列的线性基为权值位数,即至多为log个。

    所以我们可以知道异或值为总异或值的个数的至多有log次,次数不多。

    所以我们可以对整个序列做至多log次FWT,求出至少在第几次存在异或值等于总异或值,n-次数即为答案。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=6e5+5;
    int n,a[N],t=1,l,mx,sum,v[N],b[N],c[N];
    il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
    il void fwt(int *s,int tp){
        for(int i=1;i<t;i<<=1){
            for(int j=0;j<t;j+=i<<1){
                for(int k=0;k<i;k++){
                    int A=s[j+k],B=s[i+j+k];
                    s[j+k]=A+B;s[i+j+k]=A-B;
                    if(tp==-1)s[j+k]=s[j+k]/2,s[i+j+k]=s[i+j+k]/2;
                }
            }
        }
    }
    int main()
    {
        n=read();for(int i=1;i<=n;i++){int x=read();b[x]=1;mx=max(mx,x);sum^=x;}
        while(t<=mx)t<<=1,l++;
        if(sum==0){printf("%d
    ",n);return 0;}
        if(b[sum]){printf("%d
    ",n-1);return 0;}
        fwt(b,1);for(int i=0;i<t;i++)c[i]=b[i];
        for(int k=1;;k++){
            if(k>1){
                for(int i=0;i<t;i++)if(c[i]!=0)c[i]=1;
                fwt(c,1);
            }
            for(int i=0;i<t;i++)c[i]=c[i]*b[i];
            fwt(c,-1);
            if(c[sum]!=0){printf("%d
    ",n-k-1);return 0;}
        }
        return 0;
    }
    View Code
  • 相关阅读:
    014.Python函数
    013.Python的文件操作
    012.Python的字典和集合的相关函数
    011.Python的列表的相关操作
    010.Python字符串的格式化
    009.Python字符串相关函数
    008.Python循环for循环
    007.Python循环语句while循环嵌套
    Java 反射机制 初探*
    Java 正则初探
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10274272.html
Copyright © 2020-2023  润新知