zoukankan      html  css  js  c++  java
  • 【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
    ", 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 }
  • 相关阅读:
    [转]Android自定义控件三部曲系列完全解析(动画, 绘图, 自定义View)
    【深入Java虚拟机】之二:Java垃圾回收机制
    【深入Java虚拟机】之一:Java内存模型
    java线程安全
    [转]软键盘用法总结
    jqgrid 不能选中行, 每次点击单元格都自动选中第一行
    TextBox禁用与启用的方法
    Easyui TextBox 添加事件的方法
    运行程序时抛出异常“找不到请求的 .Net Framework Data Provider。可能没有安装。”
    序列 Sequence
  • 原文地址:https://www.cnblogs.com/cocottt/p/6685418.html
Copyright © 2011-2022 走看看