线性基例题

例题1

【模板】线性基 - 洛谷

考察最大值查询

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int mo = 1e3;
const int N = 2e5 + 5;
ll d[70];
void add(ll x)
{
	for (int i = 50; i >= 0; i--)
	{
		if (x & (1ll << i)) //注意,如果i大于31,前面的1的后面一定要加ll
		{
			if (d[i])x ^= d[i];
			else
			{
				d[i] = x;
				break;//插入成功就退出
			}
		}
	}
}
ll ans()
{
	ll anss = 0;
	for (int i = 50; i >= 0; i--) //记得从线性基的最高位开始
		if ((anss ^ d[i]) > anss)anss ^= d[i];
	return anss;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n, x;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> x;
		add(x);
	}
	cout << ans();
	return 0;
}

例题2

考察存在情况的判断

xor序列

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int mo = 1e3;
const int N = 2e5 + 5;
ll b[70], d[70];
void add(ll x)
{
	for (int i = 60; i >= 0; i--)
	{
		if (x & (1ll << i)) //注意,如果i大于31,前面的1的后面一定要加ll
		{
			if (d[i])x ^= d[i];
			else
			{
				d[i] = x;
				break;//插入成功就退出
			}
		}
	}
}
bool query(int y)
{
	for (int i = 60; i >= 0; i--)
	{
		if (y & (1ll << i)) //注意,如果i大于31,前面的1的后面一定要加ll
		{
			if (b[i])y ^= b[i];
			else
			{
				b[i] = y;
				return 0;
			}
		}
	}
	return 1;
}
ll ans()
{
	ll anss = 0;
	for (int i = 50; i >= 0; i--) //记得从线性基的最高位开始
		if ((anss ^ d[i]) > anss)anss ^= d[i];
	return anss;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n, x, y;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> x;
		add(x);
	}
	int q;
	cin >> q;
	while (q--)
	{
		memcpy(b,d,sizeof d);
		cin >> x >> y;
		y^=x;
		if (query(y))
		{
			cout << "YES\n";
		}
		else
		{
			cout << "NO\n";
		}
	}
	return 0;
}

例题三 


[TJOI2008]彩灯 - 洛谷

我们把开关看成原数列,而灯的开闭就是其二进制分解的结果,两个或者若干个开关异或的结果就是最终灯的开闭情况,用线性基表示全部结果,

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int mo = 2008;
const int N = 2e5 + 5;
ll b[70], d[70];
void add(ll x)
{
	for (int i = 60; i >= 0; i--)
	{
		if (x & (1ll << i)) //注意,如果i大于31,前面的1的后面一定要加ll
		{
			if (d[i])x ^= d[i];
			else
			{
				d[i] = x;
				break;//插入成功就退出
			}
		}
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n, m, x;
	cin >> n >> m;
	char c;
	while (m--)
	{
		x=0;
		for (int i = 0; i < n; i++)
		{
			cin >> c;
			if (c == 'O')
			{
				x|=1ll<<i;
			}
		}
		add(x);
	}
	ll ans=1;
	for(int i=0;i<=60;i++)
	{
		if(d[i]!=0)
		{
			ans<<=1;
			ans%=mo;
		}
	}
	cout<<ans;
	return 0;
}

例题4

牛客(Zero XOR Subset)-less

cf(Zero XOR Subset)-less

考察性质2,3. 根据题意,我们发现一个异或子段可以是前缀异或数组相异或得到的,所以线性基可以记载全部n个异或前缀数组的异或情况,性质2保证了它们不可能存在异或结果是0的情况,性质3保证了这些子段的异或值都能够被表示。而值得注意的是,如果全部n个数异或之后不为0,那么我们线性基一定能够将这n个数都囊括进去,再利用这个大的前缀异或值去“分解”剩余小的。可如果n个数异或之后是0,那么至少这一结果不满足线性基表示非零的性质,从而无法被加入,无法参与切割,最右端点也不再是n

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int mo = 2008;
const int N = 2e5 + 5;
ll a[N], d[70];
void add(ll x)
{
	for (int i = 60; i >= 0; i--)
	{
		if (x & (1ll << i)) //注意,如果i大于31,前面的1的后面一定要加ll
		{
			if (d[i])x ^= d[i];
			else
			{
				d[i] = x;
				break;//插入成功就退出
			}
		}
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n, now=0;
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		now^=a[i];
		add(now); 
	}
	
	if(now==0)
	{
		cout<<-1;
		return 0;
	}
	
	ll ans=0;
	for(int i=0;i<=60;i++)
	{
		if(d[i]!=0)
		{
			ans++;
		}
	}
	cout<<ans;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个线性规划问题的例题和单纯形法的求解步骤: 假设有一家化工公司要生产两种产品 A 和 B。生产一个单位的 A 需要 1 个单位的原料 X 和 2 个单位的原料 Y;生产一个单位的 B 需要 2 个单位的原料 X 和 1 个单位的原料 Y。公司现在有 100 个单位的 X 和 80 个单位的 Y,而且 A 和 B 的销售利润分别是 5 和 4。问这家公司应该如何安排生产才能最大化利润? 我们可以用线性规划模型来描述这个问题: 目标函数:Maximize 5A + 4B 约束条件: A + 2B <= 100 (原料 X 的限制) 2A + B <= 80 (原料 Y 的限制) A, B >= 0 (非负性约束) 接下来,我们可以用单纯形法来求解这个问题。 首先,将约束条件转化为标准形式: A + 2B + S1 = 100 2A + B + S2 = 80 A, B, S1, S2 >= 0 其中,S1 和 S2 是人造变量,它们的系数都为 1。 然后,构造初始单纯形表: | 变量 | 非变量 | 系数 | 系数 | 系数 | 右端常数 | |--------|----------|------|------|------|----------| | S1 | A | 1 | 2 | 0 | 100 | | S2 | B | 2 | 1 | 0 | 80 | | Z | | -5 | -4 | 0 | 0 | 其中,Z 表示目标函数,变量是 S1 和 S2,非变量是 A 和 B。 接下来,我们要进行迭代,找到最优解。 第一步,选择进入变量。根据单纯形法的规则,我们需要选择目标函数系数最小的非变量作为进入变量。在这个例子中,B 的系数最小,因此选择 B 作为进入变量。 第二步,选择离开变量。根据单纯形法的规则,我们需要选择进入变量系数为正的约束条件中,右端常数最小的那个约束条件对应的变量作为离开变量。在这个例子中,第二个约束条件对应的变量 S2 的右端常数最小,因此选择 S2 作为离开变量。 第三步,进行行变换。根据单纯形法的规则,我们需要将离开变量所在的行变换为新的变量。具体来说,我们需要将 S2 所在的行除以 S2 的系数,并让 S2 的系数变为 1。其他行需要进行相应的调整,使得非变量的系数都为 0。行变换后,新的单纯形表如下: | 变量 | 非变量 | 系数 | 系数 | 系数 | 右端常数 | |--------|----------|------|-------|------|----------| | S1 | A | 4/5 | 3/5 | 0 | 60 | | B | S2 | 2/5 | 1/5 | 0 | 40 | | Z | | -2 | -11/5 | 0 | -160 | 第四步,检查最优性。如果目标函数系数都为负数,那么当前解就是最优解。否则,返回第一步继续迭代。 在这个例子中,目标函数系数不全为负数,因此需要继续迭代。重复上述步骤,选择 A 作为进入变量,S1 作为离开变量,进行行变换,得到新的单纯形表: | 变量 | 非变量 | 系数 | 系数 | 系数 | 右端常数 | |--------|----------|------|-------|------|----------| | A | S1 | 5/4 | 1/4 | 0 | 25 | | B | S2 | 1/4 | -1/4 | 0 | 15 | | Z | | -9/4 | -7/4 | 0 | -125 | 此时,目标函数系数都为负数,因此当前解就是最优解。最优解是在 A = 25,B = 15 时取得的,此时目标函数值为 5*25 + 4*15 = 155,即这家公司应该生产 25 个单位的 A 和 15 个单位的 B,才能最大化利润。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值