首页 > 其他 > 详细

线性基练习

时间:2020-11-19 22:00:59      阅读:41      评论:0      收藏:0      [点我收藏+]

暑假练过线性基,当时学习了线性基在博弈,图上异或计数的应用,这段时间又做了几道线性代数的题,一起总结一下。

$1.bzoj 3105$

代码很简单,将数从大到小排序后一个个再插入线性基,证明要用拟阵,不会,暂时也不打算去学。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 155;
const double eps = 1e-8;

struct Linear_Basis{
    int p[35],cnt;
    void init() {
        memset(p,0,sizeof(p));
        cnt=0;
    }
    bool Insert(int x) {
        for(int i=31;i>=0;i--) {
            if((x>>i) & 1) {
                if(!p[i]) {
                    p[i]=x;
                    break;
                }
                x^=p[i];
            }
        }
        if(x>0) cnt++;
        return (x>0);
    }
}sol;

int a[105];

int main() {
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);reverse(a+1,a+n+1);
    sol.init();
    ll ans=0;
    for(int i=1;i<=n;i++) {
        ans+=a[i];
        int f = sol.Insert(a[i]);
        if(f) ans-=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}

$2.bzoj 2844$

题意:给$x$和$n$个数,求在这$n$个数张成的线性空间中,$x$是从小到大的第一次出现的位置。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 100005;
const int INF = 1000000007;
const int mod = 10086;

struct Linear_Basis{
    int p[40];
    int cnt;
    bool flag;
    void init() {
        memset(p,0,sizeof(p));
        cnt=0;
    }
    bool Insert(int x) {
        for(int i=31;i>=0;i--) {
            if((x>>i) & 1) {
                if(!p[i]) {
                    p[i]=x;
                    break;
                }
                x^=p[i];
            }
        }
        if(x>0) cnt++;
        return (x>0);
    }
}sol;

int vec[40];

int main() {
    int n,m;scanf("%d",&n);
    sol.init();
    for(int i=1;i<=n;i++) {
        int x;scanf("%d",&x);
        sol.Insert(x);
    }
    scanf("%d",&m);
    ll ans=0;

    int tot=0;
    for(int i=0;i<=31;i++) {
        if(((m>>i) & 1) && sol.p[i]>0) {

            ans += (1ll<<tot)%mod;
            ans %= mod;
        }
        if(sol.p[i]>0) tot++;
    }
    for(int i=1;i<=n-sol.cnt;i++) {
        ans=ans*2ll%mod;
    }
    ans++;ans%=mod;
    printf("%lld\n",ans);
    return 0;
}

$3.bzoj 3237,bzoj 3563,bzoj 3569$

三道本质一样的题,先从图中找出一个生成树,生成树的边称为树边,其余边成为非树边,非树边随机权值,树边的权值是与该树边共顶点的非树边权值异或和。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 100005;
const int INF = 1000000007;

struct node {
    int nxt,to;
};

node e[500005];
int head[maxn],tot;
bool vis[maxn];
int b[500005],a[maxn];

void add(int u,int v) {
    e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;
}

void dfs0(int u,int fa) {
    vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt) {
        int v = e[i].to;
        if(!vis[v]) {
            dfs0(v,u);
        }
        else {
            b[i]=rand()%INF+1;
            a[u]^=b[i];
            a[v]^=b[i];
        }
    }
}

void dfs1(int u,int fa) {
    vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt) {
        int v = e[i].to;
        if(vis[v]) continue;
        dfs1(v,u);
        b[i]^=a[v];
        a[u]^=a[v];
    }
}

struct Linear_Basis{
    int p[33],cnt;
    void init() {
        cnt=0;
        memset(p,0,sizeof(p));
    }
    bool Insert(int x) {
        for(int i=31;i>=0;i--) {
            if((x>>i) & 1) {
                if(!p[i]) {
                    p[i]=x;
                    break;
                }
                x^=p[i];
            }
        }
        if(x>0) cnt++;
        return (x>0);
    }
}sol;

int main() {
    srand(19491001);
    tot=0;
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) {
        int u,v;scanf("%d%d",&u,&v);
        if(u>v) swap(u,v);
        add(u,v);
    }
    dfs0(1,-1);
    memset(vis,0,sizeof(vis));
    dfs1(1,-1);
    int q;scanf("%d",&q);
    int ans=0;
    while(q--) {

        int k;scanf("%d",&k);
        sol.init();
        int f=1;
        for(int i=1;i<=k;i++) {
            int id;scanf("%d",&id);
            //printf("x = %d\n",id^ans);
            if(sol.Insert(b[(id^ans)])==0) {
                f=0;
            }
        }
        if(f) {
            printf("Connected\n");
        }
        else printf("Disconnected\n");
        if(f) ans++;
        //printf("end : ans = %d\n",ans);
    }
    return 0;
}

$4.bzoj 3811$

神题,还不会。

线性基练习

原文:https://www.cnblogs.com/ArcherLwz/p/14008030.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!