2844: albus就是要第一个出场
分析:
和HDU3949差不多互逆,这里需要加上相同的数。
结论:所有数任意异或,构成的数出现一样的次数,次数为$2^{n-cnt}$,cnt为线性基的大小。
结论:集合中所有异或值为0的集合有$2^{n-cnt}$个(包括空集)。
证明及详细过程参考:https://blog.sengxian.com/algorithms/linear-basis,https://blog.csdn.net/jaihk662/article/details/78654679
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 char buf[100000],*_p1 = buf,*_p2 = buf; 6 #define nc() (_p1==_p2&&(_p2=(_p1=buf)+fread(buf,1,100000,stdin),_p1==_p2) ? EOF : *_p1++) 7 inline int read() { 8 int x=0,f=1;char ch=nc();for(;!isdigit(ch);ch=nc())if(ch=='-')f=-1; 9 for (;isdigit(ch);ch=nc())x=x*10+ch-'0';return x*f; 10 } 11 12 const int N = 100010; 13 const int m = 30; 14 const int mod = 10086; 15 16 int a[N],b[100]; 17 vector<int> v; 18 int n,cnt; 19 20 inline void build() { 21 for (int i=1; i<=n; ++i) 22 for (int j=m; j>=0; --j) 23 if ((a[i] >> j) & 1) { 24 if (b[j]) a[i] ^= b[j]; 25 else { 26 cnt++;b[j] = a[i]; 27 for (int k=j-1; k>=0; --k) if (b[k]&&((b[j]>>k)&1)) b[j] ^= b[k]; // 这两行可以省掉,因为下面用不到,只判断一下 28 for (int k=j+1; k<=m; ++k) if ((b[j]>>k)&1) b[k] ^= b[j]; 29 break; 30 } 31 } 32 for (int i=0; i<=m; ++i) 33 if (b[i]) v.push_back(i); // --push_back(i),说明(1<<i)的位置有1 34 } 35 inline int ksm(int a,int b) { 36 int ans = 1; // -- 37 while (b) { 38 if (b & 1) ans = (ans * a) % mod; 39 a = (a * a) % mod; 40 b >>= 1; 41 } 42 return ans % mod; 43 } 44 inline void solve() { 45 int q = read(); 46 if (q == 0) {cout << 1;return ;} 47 int rnk = 0,sz = v.size(); 48 for (int i=0; i<sz; ++i) // 得到排名,从小的开始取,看v[i]能否才参与构成q,如果可以加上2^i,i为v[i]的排名(第i个线性基元素) 49 if ((q >> v[i]) & 1) rnk += (1 << i); 50 cout << (rnk % mod * ksm(2,n-cnt) + 1) % mod; // 加一:包括空集 51 } 52 int main() { 53 n = read(); 54 for (int i=1; i<=n; ++i) a[i] = read(); 55 build(); 56 solve(); 57 return 0; 58 }