【BZOJ3811/UOJ36】 玛里苟斯

Description

魔法之龙玛里苟斯最近在为加基森拍卖师的削弱而感到伤心,于是他想了一道数学题。
S 是一个可重集合,S={a1,a2,…,an}。
等概率随机取 S 的一个子集 A={ai1,…,aim}。
计算出 A 中所有元素异或 x, 求 xk 的期望。

Input

第一行两个正整数 n, k。
以下 n 行每行一个整数,表示 ai。

Output

如果结果是整数,直接输出。如果结果是小数(显然这个小数是有限的),输出精确值(末尾不加多余的 0)。

Sample Input

4 2
0
1
2
3

Sample Output

3.5

HINT

限制与约定

1≤n≤100000,1≤k≤5,ai≥0。最终答案小于 2^63 。k=1,2,3,4,5 各自占用 20% 的数据

Source

2015年国家集训队测试

Solution

被学长安利去做这道题。。。线性基。

考虑一个性质:如果把集合内的一个数异或上另一个数,则这个集合的子集的异或和的集合不变。

什么叫做子集的异或和的集合?就是你从一个集合中选出一个子集,这个有2^n种选法,把选出来的数异或起来,然后这些异或起来的数组成的集合。

考虑证明:

假如我们一开始的集合是{a,b,...},我们把b异或上a,得到{a,a^b,...}。

然后原来和b有关但与a无关的子集的异或和,我们可以用a异或上a^b来代替;

原来和a和b都有关的子集的异或和,我们现在可以直接用a^b来代替。

其他的集合因为没有变,所以还是不变的。

那么总共产生的集合还是没有变。

既然我们有这么一个操作,那么我们就可以按位高斯消元了。我们把原集合高斯消元后得到的集合称作线性基(听别人说好像也叫秩?我对线代一无所知,所以不是很懂)。

可以证明线性基的个数是log权值的。

这题就是把式子展开完dfs一下。。。(你要是愿意每个子任务写k个for也是可以的)

Code

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 
  6 #ifdef WIN32
  7     #define LL "%I64d"
  8 #else
  9     #define LL "%lld"
 10 #endif
 11 
 12 #ifdef CT
 13     #define debug(...) printf(__VA_ARGS__)
 14     #define setfile() 
 15 #else
 16     #define debug(...)
 17     #define filename ""
 18     #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
 19 #endif
 20 
 21 #define R register
 22 #define getc() (_S == _T && (_T = (_S = _B) + fread(_B, 1, 1 << 15, stdin), _S == _T) ? EOF : *_S++)
 23 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
 24 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
 25 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
 26 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
 27 #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
 28 char _B[1 << 15], *_S = _B, *_T = _B;
 29 typedef unsigned long long ull;
 30 inline ull F()
 31 {
 32     R char ch; R ull cnt = 0; R bool minus = 0;
 33     while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
 34     ch == '-' ? minus = 1 : cnt = ch - '0';
 35     while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
 36     return minus ? -cnt : cnt;
 37 }
 38 typedef long long ll;
 39 ull b[100], c[100];
 40 int top, m, sum, n, k, tmp, sn[110], maxlen;
 41 ll ans;
 42 bool flag;
 43 void dfs(R int step, R ull state)
 44 {
 45     if (!step)
 46     {
 47         R int cnt = 0;
 48         memset(c, 0, (m + 2) << 3);
 49         for (R int i = 0; i <= m; ++i)
 50         {
 51             R ull x = b[i] & state;
 52             for (; x; )
 53             {
 54                 tmp = __builtin_ctzll(x);
 55                 if (!c[tmp])
 56                 {
 57                     c[tmp] = x;
 58                     break;
 59                 }
 60                 x ^= c[tmp];
 61             }
 62         }
 63         for (R int i = m; i >= 0; --i)
 64             if (c[i])
 65                 for (R int j = i - 1; j >= 0; --j)
 66                     if (c[j] & (1ull << i))
 67                         c[j] ^= c[i];
 68         R ull summ = 0;
 69         for (R int i = 0; i <= m; ++i) if (c[i]) ++cnt, summ ^= c[i];
 70         if (summ != state) return ;
 71 //        printf("%d %d\n", cnt, sum );
 72         if (sum < cnt)
 73         {
 74             ++sn[cnt - sum];
 75             cmax(maxlen, cnt - sum);
 76         }
 77         else ans += 1ull << (sum - cnt);
 78         return ;
 79     }
 80     for (R int i = 0; i <= m; ++i)
 81     {
 82         sum += i;
 83         dfs(step - 1, state | (1ull << i));
 84         sum -= i;
 85     }
 86 }
 87 int main()
 88 {
 89 //    setfile();
 90     n = F(), k = F();
 91     for (R int i = 1; i <= n; ++i)
 92     {
 93         R ull x = F();
 94         cmax(m, 63 - __builtin_clzll(x));
 95         for (; x; )
 96         {
 97             tmp = __builtin_ctzll(x);
 98             if (!b[tmp])
 99             {
100                 b[tmp] = x;
101                 break;
102             }
103             x ^= b[tmp];
104         }
105     }
106     for (R int i = m; i >= 0; --i)
107         if (b[i])
108             for (R int j = i - 1; j >= 0; --j)
109                 if (b[j] & (1ull << i))
110                     b[j] ^= b[i];
111 //    for (R int i = 0; i <= m; ++i) printf("%llu ", b[i] );
112     dfs(k, 0);
113     for (R int i = maxlen; i; --i)
114     {
115         sn[i - 1] += sn[i] >> 1;
116         sn[i] %= 2;
117     }
118     ans += sn[0];
119     printf("%llu", ans );
120     sn[1] ? puts(".5") : 0;
121     return 0;
122 }

 

转载于:https://www.cnblogs.com/cocottt/p/6685418.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于C++&OPENCV 的全景图像拼接 C++是一种广泛使用的编程语言,它是由Bjarne Stroustrup于1979年在新泽西州美利山贝尔实验室开始设计开发的。C++是C语言的扩展,旨在提供更强大的编程能力,包括面向对象编程和泛型编程的支持。C++支持数据封装、继承和多态等面向对象编程的特性和泛型编程的模板,以及丰富的标准库,提供了大量的数据结构和算法,极大地提高了开发效率。12 C++是一种静态类型的、编译式的、通用的、大小写敏感的编程语言,它综合了高级语言和低级语言的特点。C++的语法与C语言非常相似,但增加了许多面向对象编程的特性,如类、对象、封装、继承和多态等。这使得C++既保持了C语言的低级特性,如直接访问硬件的能力,又提供了高级语言的特性,如数据封装和代码重用。13 C++的应用领域非常广泛,包括但不限于教育、系统开发、游戏开发、嵌入式系统、工业和商业应用、科研和高性能计算等领域。在教育领域,C++因其结构化和面向对象的特性,常被选为计算机科学和工程专业的入门编程语言。在系统开发领域,C++因其高效性和灵活性,经常被作为开发语言。游戏开发领域中,C++由于其高效性和广泛应用,在开发高性能游戏和游戏引擎中扮演着重要角色。在嵌入式系统领域,C++的高效和灵活性使其成为理想选择。此外,C++还广泛应用于桌面应用、Web浏览器、操作系统、编译器、媒体应用程序、数据库引擎、医疗工程和机器人等领域。16 学习C++的关键是理解其核心概念和编程风格,而不是过于深入技术细节。C++支持多种编程风格,每种风格都能有效地保证运行时间效率和空间效率。因此,无论是初学者还是经验丰富的程序员,都可以通过C++来设计和实现新系统或维护旧系统。3

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值