albus就是要第一个出场

一、题目

点此看题

二、解法

首先考虑没有重复(序列个数等于线性基个数)的情况,那么问题就是求一个值的排名(跟求排名的值差不多)

如果有重复的情况呢?我们考虑一个值在线性基 i i 位被异或为 0 0 ,那我们就把这个值归类到 i i 位,设有 w w 个多余的值。如果一个位置被选取了,那么选奇数个数的子集方案数 2 w 2^w ,否则可以选当前位没有被选取,那么选偶数也是 2 w 2^w ,总方案数就是 2 n m 2^{n-m} m m 是重复的个数。

代码也就不难了,仿照求排名的值。

#include <cstdio>
#define int long long
const int jzm = 10086;
int read()
{	
	int x=0,flag=1;char c;
	while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*flag;
}
int n,m,k,ans,p[40];
void ins(int x)
{
	for(int i=30;i>=0;i--)
	{
		if(!(x>>i)) continue;
		if(!p[i]) {p[i]=x;break;}
		x^=p[i];
	}
	if(!x) m=m*2%jzm;
}
void work()
{
	for(int i=1;i<=30;i++)
		for(int j=0;j<i;j++)
			if(p[i]&(1<<j))
				p[i]^=p[j];
}
signed main()
{
	n=read();m=1;
	for(int i=1;i<=n;i++)
		ins(read());
	work();
	k=read();
	for(int i=0,t=1;i<=30;i++)
		if(p[i])
		{
			if((k>>i)&1) ans+=t;
			t<<=1;
		}
	printf("%lld\n",(ans*m+1)%jzm);
}
原创文章 430 获赞 14 访问量 1万+

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/106056706