BZOJ2844 || 洛谷P4869 albus就是要第一个出场【线性基】

Time Limit: 6 Sec
Memory Limit: 128 MB

Description

已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x <= n }, S 的幂集2^S定义为S 所有子
集构成的集合。定义映射 f : 2^S -> Zf(空集) = 0f(T) = XOR A[t] , 对于一切t属于T现在albus把2^S中每个集
合的f值计算出来, 从小到大排成一行, 记为序列B(下标从1开始)。 给定一个数, 那么这个数在序列B中第1
次出现时的下标是多少呢?

Input

第一行一个数n, 为序列A的长度。接下来一行n个数, 为序列A, 用空格隔开。最后一个数Q, 为给定的数.

Output

共一行, 一个整数, 为Q在序列B中第一次出现时的下标模10086的值.

HINT

1 <= N <= 10,0000
其他所有输入均不超过10^9


题目分析

一开始不知道结论的话还真不好想

  • 若原数集大小为n,线性基大小为k,则共有 2 k 2^k 2k种不同的异或和,每个异或和出现次数为 2 n − k 2^{n-k} 2nk

有这个结论后题目转化为求有多少种异或和小于Q,记这个个数为cnt
那么有 a n s = c n t ∗ 2 n − k + 1 ans=cnt*2^{n-k}+1 ans=cnt2nk+1,其中+1是因为题意中空集映射到0

关于个数求法具体看代码和注释吧

#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
typedef double dd;
 
int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}
 
const int mod=10086;
const int maxn=55;
int n;
int a[maxn],Q;
int rem[maxn],k;
 
int qpow(int a,int b)
{
    int res=1;
    while(b>0){
        if(b&1) res=(res*a)%mod;
        a=(a*a)%mod; b>>=1;
    }
    return res;
}
 
void ins(int x)
{
    for(int i=30;i>=0;--i)
    if(x&(1ll<<i)){
        if(!a[i]){ a[i]=x; break;}
        else x^=a[i];
    }
}
 
int main()
{
    n=read();
    for(int i=1;i<=n;++i) ins(read());
     
    Q=read();
    for(int i=0;i<=30;++i)
    if(a[i]) rem[k++]=i;
     
    lt res=0;
    for(int i=0;i<k;++i)
    if(Q&(1<<rem[i])) res=(res+(1<<i))%mod;
    //若Q的这一位也为1,那么前i-1个线性基数值可以任意取若干个异或,其值必定小于Q
    //每个可以选或不选,所以是2^{i-1} (i是从0开始枚举的所以实际没-1)
     
    printf("%lld",(res*qpow(2,n-k)%mod+1)%mod);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值