首页 > 其他分享 >线性基相关

线性基相关

时间:2024-10-24 20:36:05浏览次数:1  
标签:return int ll fo 线性 相关 include define

[ABC236F] Spices

有 \(2 ^ N - 1\) 个数字,分别编号为 \(1, 2, \dots, 2 ^ N - 1\),想获得编号为 \(i\) 的数字需要支付 \(c_i\) 的代价。

现在你可以从这些数字中选出一些数,使得你可以通过你选择的某些数的编号的异或和来表示出 \([1, 2 ^ N - 1]\) 中的所有数。

请你求出最少需要支付多少代价。

线性基的基本贪心,按照\(c_i\)从小到大排序后,依次插入,可以插入的就是加入答案中的数。

#include<bits/stdc++.h>
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define lc (o<<1)
#define rc ((o<<1)|1)
#define mk(x,y) make_pair((x),(y))
#define eb emplace_back
#define A puts("Yes")
#define B puts("No")
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef long long i64;
const ll inf=1ll<<60;
const ll mo1=1e9+9;
const ll mo2=1e9+7;
const ll P=131;
const ll Q=13331;
const int N=5e5+5;
const int M=2e6+5;
struct Base{
	ll p[35];
	bool ins(ll x){
		fd(i,31,0) {
			if ((x>>i)&1) {
				if (!p[i]) {
					p[i]=x;
					return 1;
				}
				else x^=p[i];
			}
		}
		return 0;
	}
};
Base t;
ll n;
struct node{
	ll i,c;
};
node a[N];
int main(){
//	freopen("data.in","r",stdin);
	
	scanf("%lld",&n);
	n=(1<<n)-1;
	fo(i,1,n) {
		scanf("%lld",&a[i].c);
		a[i].i=i;
	}
	sort(a+1,a+n+1,[](node a,node b){
		return a.c<b.c;	
	});
	
	ll ans=0;
	fo(i,1,n) {
		if (t.ins(a[i].i)) ans+=a[i].c;
	}
	printf("%lld",ans);

	
	return 0;
}
 
  

[WC2011] 最大XOR和路径

给出所有边权,问从1-n的最大XOR和路径是多少。

本质上就是随便选取一条路径的xor和,以及其它所有的环,全部丢到线性基里面。
然后就是贪心取最大值。

#include<bits/stdc++.h>
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define lc (o<<1)
#define rc ((o<<1)|1)
#define mk(x,y) make_pair((x),(y))
#define eb emplace_back
#define A puts("Yes")
#define B puts("No")
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef long long i64;
const ll inf=1ll<<60;
const ll mo1=1e9+9;
const ll mo2=1e9+7;
const ll P=131;
const ll Q=13331;
const int N=5e5+5;
const int M=2e6+5;
const ll mo=1e9+7;
struct Base{
	ll p[100];
	ll rank=0;
	bool ins(ll x){
		fd(i,60,0) {
			if ((x>>i)&1) {
				if (!p[i]) {
					p[i]=x;
					rank++;
					return 1;
				}
				else x^=p[i];
			}
		}
		return 0;
	}
};
Base t;

ll head[N],nex[M*2],to[M*2],tot=1;
ll w[M*2],val[N];
bool vis[N];
ll n,m,x,y,z;
void add(ll x,ll y,ll z){
	to[++tot]=y; nex[tot]=head[x]; head[x]=tot; w[tot]=z;
}
void dfs(int x){
	vis[x]=1;
	for(int i=head[x];i;i=nex[i]) {
		int v=to[i];
		if (vis[v]) {
			t.ins(w[i]^val[v]^val[x]);
		}
		else {
			val[v]=val[x]^w[i];
			dfs(v);
		}
	}
}
int main(){
//	freopen("data.in","r",stdin);
	
	
	scanf("%lld %lld",&n,&m);
	fo(i,1,m) {
		scanf("%lld %lld %lld",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	
	dfs(1);
	ll ans=val[n];
	fd(i,60,0) ans=max(ans, ans^t.p[i]);
	printf("%lld",ans);
	
	return 0;
}
 
  

P3292 [SCOI2016] 幸运数字

给定一棵树,每个节点有一个权值\(a_i\),每次询问从x到y路径上所有点\(a_i\)组成的线性基。

每个点维护一个从它到根的线性基,并用一个vector记录这些点,计算当前点的线性基时,首先将自己的点插入,然后将父亲的线性基插入即可。

每次询问的时候,x,y的线性基中深度小于lca的全部插到一个新的线性基即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<iostream>
#include<queue>
#include<set>
//#define A puts("YES")
//#define B puts("NO")
//#define A puts("Yes")
//#define B puts("No")
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
#define lc (o<<1)
#define rc (o<<1|1)
using namespace std;
typedef long long ll;
//typedef __int128 i128;
typedef double db;
const int N=1e5+5;
int f[21][N],d[N],n,x,y,q;
vector<int> e[N],v[N];
ll a[N];
struct lb{
	lb(){
		fo(i,0,60) p[i]=0;
	}
	ll p[61];
	
	bool ins(ll x){
		fd(i,60,0) {
			if ((x>>i)&1) {
				if (p[i]) x^=p[i];
				else {
					p[i]=x;
					return 1;
				}
			}
		}
		return 0;
	}
	
	ll askmax() {
		ll ans=0;
		fd(i,60,0) ans=max(ans, ans^p[i]);
		return ans;
	}
};
vector<int> get(vector<int> t,int x){
	vector<int> temp;
	temp.clear();
	
	lb r;
	if (r.ins(a[x])) temp.push_back(x);
	for (int i:t) if (r.ins(a[i])) temp.push_back(i);
	return temp;
}
void dfs(int x,int y){
	v[x]=get(v[y], x);
	for (int v:e[x]) {
		if (v==y) continue;
		f[0][v]=x;
		d[v]=d[x]+1;
		dfs(v,x);
	}
}
int lca(int x,int y){
	if (d[x]<d[y]) swap(x,y);
	fd(k,20,0) if (d[f[k][x]]>=d[y]) x=f[k][x];
	fd(k,20,0) {
		if (f[k][x]^f[k][y]) x=f[k][x],y=f[k][y];
	}
	if (x!=y) return f[0][x];
	return x;
}
void work(int x,int y){
	lb t;
	
	int l=lca(x,y);
	for (int i:v[x]) if (d[i]>=d[l]) t.ins(a[i]);
	for (int i:v[y]) if (d[i]>=d[l]) t.ins(a[i]);
	
	cout<<t.askmax()<<"\n";
}
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);
	
	
	std::ios::sync_with_stdio(false);
	cin.tie(0); 
	cout.tie(0);
	
	cin>>n>>q;
	fo(i,1,n) cin>>a[i];
	fo(i,1,n-1) {
		cin>>x>>y;
		e[x].emplace_back(y);
		e[y].emplace_back(x);
	}

	f[0][1]=1;
	v[1].emplace_back(1);
	dfs(1,0);

	fo(j,1,20) fo(i,1,n) f[j][i]=f[j-1][f[j-1][i]];
	
	while (q--) {
		cin>>x>>y;
		work(x,y);
	}

	return 0;
}                            

  
 
  



[ABC223H] Xor Query

题面翻译

  • 给定一个长度为 \(N\) 正整数序列 \(A\),\(Q\) 次询问。
  • 每次询问给出三个正整数 \(L\)、\(R\)、\(X\),请你判断能否从原序列 \(A_L\),\(A_{L+1}\),... ,\(A_R\) 中选出若干个数使其异或和为 \(X\)。

首先需要注意的是,线性基的合并是n(logn)^2,而且这个log是60的级别,所以是不太能像上一道题一样,维护一个vector的,然后暴力插入的。

我们仍然像上一道题一样,记录一个1-i组成的线性基,并且其中的数尽量靠右。
具体来说,我们复制前一个数的线性基,然后我们插入\(a_i\),使用一个贪心的策略
如果当前的数在i这一位有1,并且\(p_i\)不为0,则比较id的大小,让大的放在这一位,小的继续往后做,

#include<bits/stdc++.h>
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define eb emplace_back
#define pi pair<ll,ll>
#define mk(x,y) make_pair((x),(y))
#define lc (o<<1)
#define rc ((o<<1)|1)
#define fi first
#define se second
using namespace std;
typedef long long ll;
const ll inf = 1ll << 60;
const int N = 5e5 + 10;
struct lb {
    ll p[61], id[61];

    lb() {
        memset(p, 0, sizeof(p));
    }
    void clr() {
        memset(p, 0, sizeof(p));
    }

    void ins(ll x, ll y) {
        fd(i, 60, 0) {
            if ((x >> i) & 1) {
                if (!p[i]) {
                    p[i] = x; id[i] = y;
                    return;
                }
                else {
                    if (y > id[i]) {
                        swap(x, p[i]); swap(y, id[i]);
                    }
                    x ^= p[i];
                }
            }
        }
    }

    bool ask(ll x, ll y) {
        fd(i, 60, 0) {
            if ((x >> i) & 1) {
                if (!p[i] || id[i] < y) return 0;
                x ^= p[i];
            }
        }
        return !x;
    }
};
lb t[N];
ll n, q, a[N], l, r, x;
void solve()
{
    cin >> n >> q;
    fo(i, 1, n) cin >> a[i];

    fo(i, 1, n) {
        t[i] = t[i - 1];
        t[i].ins(a[i], i);
    }

    while (q--) {
        cin >> l >> r >> x;
        if (t[r].ask(x, l)) cout << "Yes" << "\n";
        else cout << "No" << "\n";
    }
}
int main()
{
    // freopen("data.in", "r", stdin);
    // freopen("data.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

标签:return,int,ll,fo,线性,相关,include,define
From: https://www.cnblogs.com/ganking/p/18500416

相关文章

  • FS4056E是一款单节锂离子电池恒流/恒压线性充电芯片支持NTC温度
    FS4056E是一款单节锂离子电池恒流/恒压线 性充电芯片,简单的外部应用电路非常适合便携 式设备应用,适合USB电源和适配器电源工作, 内部采用防倒充电路,不需要外部隔离二极管。 热反馈可对充电电流进行自动调节,以便在大功 率操作或高环境温度条件下对芯片温度加以限制 。FS4056E充......
  • 线性规划求解软件开发的PSP数据统计
    PSP报告1.计划(Planning)估算:本项目的主要目标是实现线性规划问题的优化模型,并通过GUI界面简化用户操作。根据任务复杂度,估算开发工作量约为40小时。2.开发(Development)2.1需求分析(Analysis)在项目中,需求包括以下几点:通过C++实现线性规划问题的优化模型。......
  • RSA算法详解及相关数学原理解析
    RSA算法详解及相关数学原理解析前言‍为了记录自己学习密码学的过程,也是为了便于个人应付相关课程的考核,故写此博客。本博客总结了怎么用C++手搓一个RSA算法,以及补补欠缺的一些数学知识和可能欠缺的一些其他算法的实现。参考了其他人的相关博客,用便于我自己理解的话和方式和......
  • 连通性相关
    强连通强连通:有向图\(G\)中每个点中可互相到达。强连通分量:极大的强连通。(最大可能的)求强连通分量先跑出图的DFS搜索树(黑边)。一个结论:一个强连通分量一定在该强连通分量中的第一个被访问的点的子树内。设根为\(u\),考虑若存在一个点\(v\)不在\(u\)子树中则一定存......
  • css3实现文字线性渐变,css3实现背景渐变
    <divclass='who1'>我是线性渐变文字我是线性渐变文字我是线性渐变文字我</div><divclass='who2'>我是背景渐变我是背景渐变我是背景渐变我是背景渐变我</div>.who1{width:400px;background:linear-gradient(toright,#ff0000,#ffff00);/*设置渐变的方向从左......
  • 栈的理解及相关算法
    一、栈的基础概念1、栈的定义栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。栈顶(Top):线性表允许进行插入删除的那一端。栈底(Bottom):固定的,不允许进行插入和删除的另一端。空栈:不含任何元素的空表。栈又......
  • 单向循环链表的实现及相关算法
    1.单向循环链表特点:每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址),末尾节点的指针域指向了头节点1.1实现过程1.1.1、构建结点structNode{ Node(intvalue=0): val(value), next(nullptr) {} intval; Node*next;};1......
  • 高等数学 7.8常系数非齐次线性微分方程
    目录一、\(f(x)=\mathrm{e}^{\lambdax}P_m(x)\)型二、\(f(x)=\mathrm{e}^{\lambdax}[P_l(x)\cos\omegax+Q_n(x)\sin\omegax]\)型二阶常系数非齐次线性微分方程的一般形式是\[y''+py'+qy=f(x)\tag{1}\]其中\(p,q\)是常数由之前的内容可知,求二阶......
  • 线性 DP
    最长上升子序列问题是一个经典的线性动态规划问题。例题:B3637最长上升子序列分析:设原始数组为\(a\),定义状态\(dp_i\)表示以\(a_i\)结尾的上升子序列的最大长度。注意这个状态定义中有两个重点,第一个重点是\(dp_i\)只维护所有原始序列中以\(a_i\)结尾的上升子序列的信......
  • 排列组合之线性排列
    1、问题1.1袋中取球袋子里有4个球,分别编号为{1,2,3,4},依次取出,按照取出的先后从左至右排列,会得到一个不同的数字(如1234,有点像双色球开奖),求输出所有的数字组合。1.2不重复的数有4个数字{0,1,2,3},问用这4个数字能组成多少种不能的4位数(0123也算,因为我们也可......