牛客多校
前置技能:
FWT介绍
线性基
线性基讲解
题解1
强烈推荐 题解2
using namespace std;
int read(){
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=1<<19,mod=1e9+7,inv2=5e8+4;
int n,a[N],b[N],v=0;
void debug(int a[],int n)
{
cout<<"数组a为"<<endl;
int top = 1;
for(int i=0;i<=n;i++)
{
if(top)top =0;
else printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
void FWT(int a[],int n,int flag){
for (int d=1;d<n;d<<=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod;
a[i+j+d]=(x-y+mod)%mod;
if (flag==-1){
a[i+j]=1LL*a[i+j]*inv2%mod;
a[i+j+d]=(1LL*a[i+j+d]*inv2%mod+mod)%mod;
}
}
}
bool check(int x,int n){
for (int i=0;i<n;i++)
b[i]=Pow(a[i],x);
FWT(b,n,-1);
b[v]=(b[v]+mod)%mod;
return b[v]>0;
}
int main(){
n=read();
memset(a,0,sizeof a);
for (int i=1;i<=n;i++){
int x=read();
v^=x;
a[x]++;
}
a[0]++;
int m=1<<19;
FWT(a,m,1);
int L=0,R=19,mid,ans=19;
while (L<=R){
mid=(L+R)>>1;
if (check(mid,m))
R=mid-1,ans=mid;
else
L=mid+1;
}
printf("%d\n",n-ans);
return 0;
}
推荐:
FFT
FWT模板:
参考
void FWT(int a[],int n)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
}
}
void UFWT(int a[],int n)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
}
}
void solve(int a[],int b[],int n)
{
FWT(a,n);
FWT(b,n);
for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod;
UFWT(a,n);
}