E-Exclusive OR 2020牛客多校第2场

https://ac.nowcoder.com/acm/contest/5667/E

线性基可以求出任意取出一些数的最大值

其实可以想到到了后面就会把线性基每一位填满了,因为数字大小只有2^18,那应该只有18位,那么做20次fwt算出答案就可以了

满秩了后答案就是有规律的了,可以知道ans[i]=ans[i-2],因为可以选两个相同的抵消掉,还是最大值

为什么不能ans[i]=ans[i-1]呢,因为会有 1 1 1 1 这种东西出现。。。

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353,r2=mod/2+1;
int a[300010],b[300010];
int ans[25];
int ad(int x,int y){
    return x+y>=mod?x+y-mod:x+y;
}
void fwtxor(int a[],int k,int arr){
    for(int mid=1;mid<k;mid<<=1){
        for(int i=0;i<k;i+=mid<<1){
            for(int j=0;j<mid;j++){
                int x=a[i+j],y=a[i+j+mid];
                a[i+j]=ad(x,y),a[i+j+mid]=ad(x,mod-y);
                if(arr==-1){
                    a[i+j]=(long long)a[i+j]*r2%mod;
                    a[i+j+mid]=(long long)a[i+j+mid]*r2%mod;
                }
            }
        }
    }
}
int main(){
    int n;
    scanf("%d",&n);
    int mx=0;
    for(int i=0;i<n;i++){
        int u;
        scanf("%d",&u);
        a[u]=1;
        mx=max(mx,u);
    }
    int k=1,l=0;
    while(k<=mx)k<<=1,l++;
    for(int i=0;i<=mx;i++)b[i]=a[i];
    fwtxor(a,k,1);
    for(int i=1;i<=l+2&&i<=n;i++){
        for(int j=k;j>=0;j--){
            if(b[j]){
                ans[i]=j;
                break;
            }
        }
        fwtxor(b,k,1);
        for(int i=0;i<k;i++)b[i]=(long long)a[i]*b[i]%mod;
        fwtxor(b,k,-1);
    }
    for(int i=1;i<=n;i++){
        if(i>l+2){
            if(i%2==l%2)printf("%d ",ans[l+2]);
            else printf("%d ",ans[l+1]);
        }
        else printf("%d ",ans[i]);
    }
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/107323556