【YBTOJ】【Luogu P3857】[TJOI2008]彩灯

链接:

洛谷

博客园

题目大意:

可以对一个长度 (n) 的 01 串的 (m) 组特定位置异或 (1),你可以选其中任意几个操作,求能异或出多少个数。

正文:

我们可以换种想法:每次操作相当于把一个 01 串和原串进行异或,求出能异或多少个数。

然后我们知道,在一个数 (x) 插入线性基时,可能会因为线性基里的元素早就已经可以异或出 (x) 而失败。而这不就是判重吗,那么重复第数字已经被去掉了,剩下的数字可以异或出最多的数,假设剩下 (k) 个数,那么 (2^k) 就是答案了。

代码:

int n, m;
char s[N];
ll a[N];

void add (ll val)
{
	for (int i = 50; i + 1; --i)
	{
		if (!(val & (1ll << i))) continue;
		if (a[i])
			val ^= a[i];
		else 
		{
			a[i] = val;
			return ;
		}
	}
}

int main()
{
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	scanf ("%d%d", &n, &m);
	for (int i = 1; i <= m; i++)
	{
		ll val = 0;
		scanf ("%s", s + 1);
		for (int i = 1; i <= n; i++)
			if (s[i] == 'O') val |= 1ll << (i - 1);
		add (val);
	}
	ll ans = 0;
	for (int i = 0; i <= 50; i ++)
		if (a[i]) ans ++;
	printf ("%lld
", (1ll << ans) % mod);
    return 0;
}

原文地址:https://www.cnblogs.com/GJY-JURUO/p/14443334.html