【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\n", (1ll << ans) % mod);
    return 0;
}

posted @ 2021-02-24 19:38  Jayun  阅读(40)  评论(0编辑  收藏  举报