2 条题解

  • 0
    @ 2025-10-5 0:21:07

    鉴定为清新小蓝题,但是我写的很狗屎。

    主要我的思路是一开始乱糊,然后胡这胡这就真了,所以代码非常难看(不过好像是实验最优解)。

    这里只写一下思路。

    首先这个 MAXMAX 看上去就很烦人,不过我们先不搭理它,我们可以先考虑直接贪心

    我们考虑最高位,发现如果我们最高位放了1,那么所有最高位是1的数我们都可以扔掉不管了,因为异或了以后肯定没有原数大。

    当然如果最高位都是1,我们就看下一位。

    以此类推,直到找到某一位,使得存在一个数,它在这一位上是0

    剩下的就是,我们还有 k1k-1 个1可以放置,然后要最大化异或 XX 的和的基础上最小化 XX

    我一开始想要延续贪心的路线,发现一位能放,当且仅当这一位上0的个数比1多,但是这么贪非常错,这就好比是01背包你写贪心,不过我一开始没多想,交上去直接 95 分,但是注意到出题人绑包了,所以这个做法绝对假完了

    前面已经说了,这本质上就是个01背包,我们做一下背包,顺便记录个方案就好了。

    为了让这篇题解看起来更反胃,我要把我的狗屎代码放上来

    #include<bits/stdc++.h>
    using namespace std;
    int a[100005];
    int s;int n,m,k;
    int B;
    int solve(int bit,int l,int r,int k,bool qdl){
    	if(!bit){
    		return 0;
    	}
    	int ok=0;
    	for(int i=r; i>=l; i--){
    		if(((1<<bit-1)&a[i])==0){
    			ok++;
    		}
    	}
    	if(qdl){
    		if(ok){
    			s|=(1<<bit-1);
    			B=bit;
    			return ok;
    		}else{
    			return solve(bit-1,l,r,k,qdl);
    		}
    	}
    }
    long long gongxian[33];
    long long f[33][33],g[33][33];
    int main(){
    	freopen("xor.in","r",stdin);
    	freopen("xor.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&k);
    	if(!k){
    		printf("0");
    		return 0;
    	}
    	for(int i=1;i <=n; i++)scanf("%d",&a[i]);
    	sort(a+1,a+1+n);int len=solve(m,1,n,k,1);
    	for(int j=B-1; j>=1; j--){
    		int ok=0;
    		for(int i=1; i<=len; i++)if(((1<<j-1)&a[i])==0)ok++;
    		if(ok*2>len)gongxian[j]=(1<<j-1)*1ll*(ok*2-len);
    	}long long mx=0;
    //	cout<<len<<endl;	
    //	cout<<B<<endl;
    	if(!B){
    		printf("0");
    		return 0;
    	}
    	for(int i=1; i<=B-1; i++){
    		for(int j=1; j<=k-1; j++){
    			f[i][j]=max(f[i-1][j],f[i-1][j-1]+gongxian[i]);
    //			cout<<f[i][j]<<endl;
    			mx=max(f[i][j],mx);
    		}
    	}memset(g,0x7f,sizeof g);
    	for(int i=0; i<=B-1; i++)g[i][0]=0;
    	long long res=1000000000000000000;
    	for(int i=1; i<=B-1; i++){
    		for(int j=1; j<=k-1; j++){
    			if(f[i-1][j-1]+gongxian[i]==f[i][j])g[i][j]=min(g[i][j],g[i-1][j-1]|(1<<i-1));
    			if(f[i-1][j]==f[i][j])g[i][j]=min(g[i][j],g[i-1][j]);
    			if(f[i][j]==mx)res=min(res,g[i][j]);
    		}
    	}if(res>(1<<m))res=0;
    	cout<<(res|(1<<B-1));
    	return 0;
    }/*
    
    */ 
    

    感谢观猴

    信息

    ID
    444
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    (无)
    递交数
    27
    已通过
    3
    上传者