D. Birthday Gift

原题链接

题解

1.异或是01变1,11变0,或是01变1,11变1,所以或的越多(即分的组越多),结果越大
2.我们令x=x+1,这样小于等于x的 问题就变成了小于x 的问题,这里我们采用逼近答案的方法。
3.对于某一位而言,如果有奇数个元素在这一位上是1,那么不管怎么分,最后的结果肯定是1,如果是偶数,那么最后的结果可能是0也可能是1,取决于分法
因为要让分的组尽可能多的情况下,最后异或的结果尽可能小,所以我们从高到低遍历,如果遇到含有偶数个1,采用把他变成0的分法,即贪心的两两配对,replace the subsegment [l,r] with al⊕al+1⊕…⊕ar

4.再就是分情况讨论,请看code

code

#define ll long long
#include<bits/stdc++.h>
using namespace std;
void solve()
{
    ll n,x;
    cin>>n>>x;
    x++;//将问题从小于等于变成小于
    vector<ll> a(n);
    for(auto &it:a) cin>>it;

    ll ans=-1;
    for(ll k=30;k>=0;k--)
    {
        vector<ll> b;
        ll occur=0;//occur代表这一位有一的数出现的个数
        for(ll i=0;i<a.size();i++)
        {
            if(occur%2==1) b.back()^=a[i];
            else b.push_back(a[i]);
            if((1LL<<k)&a[i]) occur++;
        }


        if(!(x&(1LL<<k)))//如果这个位x没有
        {
            if(occur%2==1)//但是我有
            {
                cout<<ans<<endl<<endl;//不管怎么分,异或的值肯定大于x,不用再分了,把曾经试过的正确的答案提交了
                return ;
            }
            else a=b;//我也没有,为了消除这个位的一,分法是唯一的
        }
        else
        {
            if(occur%2==0) ans=max(ans,(ll)b.size());//必须小于,逼近答案
            //如果这一位我也有,那么往下一位搜索,因为这时答案不取决于我了
        }
    }

    cout<<ans<<endl<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    ll t;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

posted @   纯粹的  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示