现在开始天晴了!|

sunzz3183

园龄:5年2个月粉丝:10关注:25

线性基学习笔记

线性基学习笔记

——by sunzz3183


引入

学高斯消元后就要学线性基啦!建议先看懂高斯消元!

介绍

给定 n 个数 ai,求一个基底

基底就是一个线性空间,即线性基。

线性基中的 t 个数 pia 中的个数都可以被 p若干数通过异或得出。

求法

高斯消元

直接贴代码:

void add(int num){
    for(int i=61;i>=0;i--)
        if((num>>i)&1)
            if(!p[i]){p[i]=num;return;}
            else num^=p[i];
    flg=1;//判断有没有0的存在
    return;
}

清新易懂,我们从大到小来枚举当前 num(2) 的第 i 位,如果发现 pi 已经有元素了,就让 num=numpi 否则插入当前的 num

问题

线性基通常有如下三个用法:

  1. 查询一个数是否能被集合中其他数异或表示

  2. 求一个集合异或最大/最小值

  3. 求一个集合异或的第k大值

下列给定三种方法的代码

查询

bool ask(){
    for(int i=61;i>=0;i--)
        if(x>>i&1)x^=p[i];
    return !x;
}

最大最小

inline int getmax(){
    int ans=0;
    for(int i=61;i>=0;i--)
        ans=max(ans,ans^p[i]);
    return ans;
}
inline int getmin(){
    if(flg)return 0;//注意判零的存在
    for(int i=0;i<=61;i++)
        if(p[i])return p[i];
}

第 k 大

k 进行二进制拆分,然后进行选数。

注意,我们可能会在插入的时候插入了一个类似这样的一个数 1111111111(2)。那么显然在求第 k 大的时候,会错序。

所谓我们要对 pi 进行重构,让 pi 成为 10000000(2) 这样的数。

void rebuild(){
    for(int i=61;i>=0;i--)
        for(int j=i-1;j>=0;j--)
            if(p[i]>>j&1)p[i]^=p[j];
    for(int i=0;i<=61;i++)if(p[i])d[cnt++]=p[i];cnt--;
}
inline int getk(int k){
    k-=flg;
    if(k>=1ll<<cnt)return -1;
    int ans=0,i=0;
    while(k)ans^=(k&1)?d[i]:0,k>>=1,i++;
    return ans;
}

本文作者:sunzz3183

本文链接:https://www.cnblogs.com/sunzz3183/p/17406945.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   sunzz3183  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
Live2D
欢迎阅读『线性基学习笔记』
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起