1 条题解

  • 1
    @ 2025-12-4 9:55:07

    从二进制高位到低位遍历,尝试合并

    具体过程如下:

    1.对于当前位j,若已合并的段中有奇数个1,那么我们不可能分裂当前合并状态,否则会导致一些更高位变成1,所以没救了,ans+=(1ll<<j)

    2.尝试合并后,若发现num1<K,那么没救了,ans+=(1ll<<j)

    否则,我们可以采用当前的方案 即另num=num1,异或和数组v[1~ num1]=v1[1~ num1]

    #include<bits/stdc++.h>
    using namespace std;
    int n,K,num,cnt[80];
    long long w[500005],v1[500005],v[500005],ans;
    void jilu(long long x)
    {
    	int t=0;
    	while(x){
    		if(x&1) cnt[t]++;
    		t++;x>>=1;
    	}
    }
    int main()
    {
    	ios::sync_with_stdio(0);
    	cin.tie(0);cout.tie(0);
    	cin>>n>>K;
    	for(int i=1;i<=n;i++){
    		cin>>v[i];jilu(v[i]);
    	}
    	num=n;
    	for(int j=59;j>=0;j--)
    	{
    		if(cnt[j]==0) continue;
    		bool cmt=0;
    		for(int i=1;i<=num;i++){
    			if((v[i]>>j)&1) cmt^=1;
    		}
    		if(cmt){
    			ans+=(1ll<<j);continue;
    		}
    		int num1=0;cmt=0;
    		memset(v1,0,sizeof v1);
    		for(int i=1;i<=num;i++)
    		{
    			if(cmt) v1[num1]^=v[i];
    			else v1[++num1]^=v[i];
    			cmt^=((v[i]>>j)&1);
    		}
    		if(num1<K) ans+=(1ll<<j);
    		else{
    			num=num1;
    			for(int i=1;i<=num1;i++) v[i]=v1[i];
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    

    记得检查传参类型,不然RE炸50分

    对1进行位运算时,记得加ll,不然WA炸50分

    • 1

    信息

    ID
    24
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    (无)
    递交数
    44
    已通过
    8
    上传者