第一行一个数n, 为序列A的长度。接下来一行n个数, 为序列A, 用空格隔开。最后一个数Q, 为给定的数.
数据范围:1 <= N <= 10,0000其他所有输入均不超过10^9
湖北省队互测
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
线性基+高斯消元~
假设线性基有k个,那么它们异或出来的值就有2^k种,而总共n个数子集个数为2^n个,因为所有种类数都相等(为什么?),所以每种的重复次数就是2^(n-k)种,然后用高斯消元求一下线性基,从小到大求和就可以了。
注意因为要求的是最小出现位置,所以ans要初始化为1~
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define modd 10086int n,m,a[100001],q[64],k,ans;void guass(int &k){ k=n; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) if(a[i]<a[j]) swap(a[j],a[i]); if(!a[i]) { k=i-1;break; } for(int j=31;~j;j--) if((a[i]>>j)&1) { q[i]=j; for(int z=1;z<=n;z++) if(i!=z && (a[z]>>j)&1) a[z]^=a[i];break; } }}int mi(int u,int v){ int tot=1; while(v) { if(v&1) tot=tot*u%modd; u=u*u%modd;v>>=1; } return tot;}int main(){ scanf("%d",&n);ans=1; for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&m); guass(k); for(int i=1;i<=k;i++) if((m>>q[i])&1) { m^=a[i]; ans=(ans+mi(2,n-i))%modd; } PRintf("%d/n",ans); return 0;}
新闻热点
疑难解答