您的位置:首页 > 其它

异或问题整理(高斯消元留坑)

2017-11-02 21:04 363 查看

单纯异或问题

题目:https://www.nowcoder.com/acm/contest/15/B

题目描述:

给定一个长度为n的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为0。

思路:前缀和

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

const int N = 2e5+5;
int a[1005],x
,cnt
;
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d",&a[i]),x[i] = x[i-1]^a[i];
long long sum = 0;
for(int i = 1;i <= n;i++)
{
for(int j = i;j <= n;j++)
sum += cnt[x[j] ^ x[i-1]];

for(int j = 1;j <= i;j++)
cnt[x[i] ^ x[j-1]]++;
}
printf("%lld\n",sum);
return 0;
}


线段树维护位异或

题目:http://codeforces.com/gym/100739/problem/A

题意:给你一个数组,对数组进行单点修改,查询区间[L,R]内所有子区间的异或和。

思路:here

线性基&&高斯消元

线性基学习见ljh2000

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2460

题意:给你n矿石(序号+魔力值),让选一些矿石使得序号异或不为0且魔力值加和最大

思路:贪心+线性基/高斯消元

按魔力值排序,贪心取大魔力值

线性基代码:

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

typedef long long ll;
const int N = 1005;
struct node{
ll num;
int val;
bool operator < (const node & p)const{
return val > p.val;
}
}a
;
ll p
;
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%lld%d",&a[i].num,&a[i].val);
sort(a+1,a+n+1);
int ans = 0;
for(int i = 1;i <= n;i++)
{
for(int j = 62;j >= 0;j--)
{
if(!(a[i].num >> j)) continue;
if(!p[j]){
p[j] = a[i].num;
ans += a[i].val;
break;
}
a[i].num ^= p[j];
}
}
printf("%d\n",ans);
return 0;
}


高斯消元代码:

暂时不会

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2115

题意:无向连通图( 图中可能有重边或自环),求1~n边权异或的最大值

思路:dfs + 线性基/高斯消元

dfs求1到点i异或值和一些环的异或值,然后求一个1到n异或值和一些环的异或的最大值

合理性:设4到1有两条路径path0,path1,如果我们选了path1,那么path0+path1为环,maxn = max(path1,path1^(path0+path1))

这个比较好理解

线性基代码:

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

typedef long long ll;
const int N = 5e4 + 5;
const int M = 1e5 + 5;
int n,m,cnt,vis
;
ll d
,p[64],a[M*4];
struct node{
int v;
ll w;
};
vector<node> G
;

void dfs(int u)
{
vis[u] = 1;
for(int i = 0;i < G[u].size();i++)
{
int v = G[u][i].v;ll w = G[u][i].w;
if(!vis[v])
{
d[v] = d[u]^w;
dfs(v);
}
else
a[++cnt] = d[v]^d[u]^w;
}
}
int main()
{
scanf("%d%d",&n,&m);
int u,v;ll w;
while(m--)
{
scanf("%d%d%lld",&u,&v,&w);
G[u].push_back({v,w});
G[v].push_back({u,w});
}
dfs(1);
for(int i = 1;i <= cnt;i++)
{
for(int j = 62;j >= 0;j--)
{
if(!(a[i] >> j)) continue;
if(!p[j]){
p[j] = a[i];
break;
}
a[i] ^= p[j];
}
}
ll ans = d
;
for(int i = 62;i >= 0;i--)
if((ans^p[i]) > ans)
ans = ans ^ p[i];
printf("%lld\n",ans);
return 0;
}


高斯消元代码:

待续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: