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]);
}
}