CF959F Mahmoud and Ehab and yet another xor task 题解

题目传送门

前置知识

线性基

解法

将操作离线下来,并按 \(\{ l \}\) 升序排序,接着顺序插入线性基并处理询问。

对于未成功插入线性基的元素 \(k\) 一定能被线性基内选出若干元素得到。故在 \(x\) 能被表出的情况下,设 \(1 \sim l\) 中成功插入线性基的元素个数为 \(siz\),对于剩下 \(l-siz\) 个元素选出若干个总方案数为 \(2^{l-siz}\),这 \(2^{l-siz}\) 种方案都存在一种在线性基中选出若干个元素使得异或起来等于 \(x\)

\(2^{l-siz}\) 即为所求。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
const ll p=1000000007;
struct node
{
    ll l,x,id;
}q[100010];
ll a[100010],d[30],ans[100010];
bool cmp(node a,node b)
{
    return a.l<b.l;
}
ll insert(ll x)
{
    for(ll i=20;i>=0;i--)
    {
        if((x>>i)&1)
        {
            if(d[i]==0)
            {
                d[i]=x;
                return 1;
            }
            x^=d[i];
        }
    }
    return 0;
}
bool check(ll x)
{
    for(ll i=20;i>=0;i--)
    {
        if((x>>i)&1)
        {
            if(d[i]==0)
            {
                return 0;
            }
            x^=d[i];
        }
    }
    return 1;
}
ll qpow(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=ans*a%p;
        }
        b>>=1;
        a=a*a%p;
    }
    return ans;
}
int main()
{
    ll n,m,siz=0,i,j;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(i=1;i<=m;i++)
    {
        cin>>q[i].l>>q[i].x;
        q[i].id=i;
    }
    sort(q+1,q+1+m,cmp);
    for(i=1,j=1;i<=m;i++)
    {
        while(j<=q[i].l)
        {
            siz+=insert(a[j]);
            j++;
        }
        ans[q[i].id]=(check(q[i].x))*qpow(2,q[i].l-siz,p);
    }
    for(i=1;i<=m;i++)
    {
        cout<<ans[i]<<endl;
    }
    return 0;
}
posted @ 2024-10-10 17:01  hzoi_Shadow  阅读(15)  评论(0编辑  收藏  举报
扩大
缩小