标签:ret html logs closed scan play ++ hid main
已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x <= n },
S 的幂集2^S定义为S 所有子集构成的集合。
定义映射 f : 2^S -> Z
f(空集) = 0
f(T) = XOR A[t](异或和)
对于一切t属于T现在albus把2^S中每个集合的f值计算出来, 从小到大排成一行, 记为序列B(下标从1开始)。
给定一个数, 那么这个数在序列B中第1次出现时的下标是多少呢?
呃啊啊还我们一个可视的题面。
这是个结论题。。。
结论:
n个数构成的线性基有k个时,那么这n个数的全部子集的异或和刚好就是线性基k个数能拼成的2k个数,每个数有2n-k个。
证明也许比较显然?
然后这题就可做了。
好无聊。。。结论题什么的。。。
但是有什么办法呢?只能记住吧。
写这篇博客的目的就是为了存一下结论。
以及推荐blog:rvalue
里面有结论的感性证明。
有了结论,代码倒挺好写的。
1 #include<cstdio> 2 #define mod 10086 3 int pw(int b,int t,int a=1){for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a;} 4 int base[33]; 5 int main(){ 6 int n,N,x,cnt=0,ans=0;scanf("%d",&n);N=n; 7 while(n--){ 8 scanf("%d",&x); 9 for(int i=30;~i;--i)if(!base[i]&&x&1<<i){base[i]=x;break;} 10 else if(x&1<<i)x^=base[i]; 11 } 12 scanf("%d",&x); 13 for(int i=30;~i;--i)if(base[i]&&x&1<<i)cnt++,ans=(ans+pw(2,N-cnt))%mod; 14 else if(base[i])cnt++; 15 printf("%d\n",ans+1); 16 17 }
标签:ret html logs closed scan play ++ hid main
原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11624654.html