1 条题解

  • 0
    @ 2025-8-24 23:18:15

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar luanyanjia
    菜 -我ら是个と大に傻む逼なり-

    搬运于2025-08-24 23:18:15,当前版本为作者最后更新于2025-06-14 18:45:51,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    AI 做不出这种题吗,挺有道理的。

    最开始做这个题的时候,我就想过如果区间异或上一个数时,如果简单地将线性基内的元素全部异或,那么只有偶数个元素的集合搞出来是正确的,所以直接做是不可行的,但在这个题上却刚刚好。

    先用带时间戳的线性基把询问区间的线性基搞出来(要离线扫描线)。

    对于第二种询问,我们将线性基中每一个数都异或 2302^{30}xx 也异或上 2302^{30},这样因为要贪心取最大值,所以最后的方案一定是取了偶数个数。否则答案不带 2302^{30} 一定更小。

    对于第一种询问,我们同样地做,这样奇数个数的方案异或出来的值带有 230>x2^{30} > x,所以一定不合法,求答案只需按位贪心,假设前面几位都顶到了上界,此时异或出来的值是确定的,然后分讨计算即可。最后答案要乘上 2rl+1cnt2^{r-l+1-cnt}cntcnt 是线性基的元素个数)。

    分讨的部分可以看看代码。

    const int V=60;
    struct Linear_Basis{
    	int b[V+5],tm[V+5];
    	inline void Insert(int x,int t,int st){
    		for(int i=st;i>=0;i--){
    			if((x>>i)&1){
    				if(b[i]){
    					if(tm[i]<t){
    						Insert(x^b[i],tm[i],i-1);
    						b[i]=x;tm[i]=t;
    						break;
    					}
    					else x^=b[i];
    				}else{
    					b[i]=x;tm[i]=t;
    					break;
    				}
    			}
    		}
    	}
    	inline int Query(int x,int v){
    		int now=v;
    		for(int i=30;i>=0;i--)
    			if(tm[i]>=x&&!(now>>i&1))
    				now^=b[i];
    		return now;
    	}
        int c[60];
        inline int Get(int l,int r,int x){
            int cnt=0,ans=0,now=0;
            c[0]=(b[0]!=0)&&tm[0]>=l;
            for(int i=1;i<=30;i++)c[i]=c[i-1]+((b[i]!=0)&&tm[i]>=l);
            for(int i=30;i>=0;i--)if(tm[i]>=l&&b[i])++cnt;
            for(int i=30;;i--){
                if(i==-1){
                    if(now<=x)Add(ans,1);
                    break;
                }
                if(x>>i&1){
                    if((now>>i&1)&&(b[i]&&tm[i]>=l))Add(ans,i?m2[c[i-1]]:1);
                    if(!(now>>i&1)){
                        if(b[i]&&tm[i]>=l){
                            now^=b[i];
                            if(i)Add(ans,m2[c[i-1]]);
                            else Add(ans,1);
                        }else{
                            if(i)Add(ans,m2[c[i-1]]);
                            else Add(ans,1);
                            break;
                        }
                    }
                }else{
                    if(now>>i&1){
                        if(!b[i]||tm[i]<l)break;
                        else if(tm[i]>=l)now^=b[i];
                    }
                }
            }
            ans=1ll*ans*m2[r-l+1-cnt]%mod;
            return ans;
        }
        inline void Clear(){
            memset(b,0,sizeof b);
            memset(tm,0,sizeof tm);
        }
    }LB;
    inline void Solve(){
        rd(n,q);
        for(int i=1;i<=n;i++)rd(a[i]);
        for(int i=1;i<=q;i++){
            int op,l,r,x;rd(op,l,r,x);
            vec[r].emplace_back(op,l,x,i);
        }
        LB.Clear();
        for(int i=1;i<=n;i++){
            LB.Insert(a[i]^(1<<30),i,30);
            for(auto[op,l,x,id]:vec[i]){
                if(op==1){
                    ans[id]=LB.Query(l,x^(1<<30))^(1<<30);
                }else{
                    ans[id]=LB.Get(l,i,x);
                }
            }
        }
        for(int i=1;i<=n;i++)vec[i].clear();
        for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
    }
    signed main(){
        m2[0]=1;
        for(int i=1;i<=500000;i++)m2[i]=m2[i-1]*2%mod;
        rd(T);
        while(T--)Solve();
        return 0;
    }
    
    • 1

    信息

    ID
    11728
    时间
    1500ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者