zoukankan      html  css  js  c++  java
  • bzoj 2844 albus就是要第一个出场

    题目传送门

      这是个通往vjudge的虫洞

      这是个通往bzoj的虫洞

    题目大意

      给定集合$S$,现在将任意$Asubseteq S$中的元素求异或和,然后存入一个数组中(下标从1开始),然后从小到大排一个序。问$q$第一次出现在$A$中的下标。

      我们可以通过线性基得到值域上有多少个异或和比$q$小,现在问题来了,怎么求$q$的下标。

      通过打表找规律,以及手动枚举可以发现一个结论。

    定理1 设线性基为$B$,那么在$S$的子集的异或和中,出现的异或和的出现的次数是$2^{left | S ight |- left | mathfrak{B} ight |} $。

      证明 假如要考虑异或出一个数$x$,基外选出的数的异或和为$s$,那么还需要$x$ ^ $s$,对于它,基内的线性表示的方法是唯一的。

      所以定理得证。

      于是再做一次快速幂,这道题就做完了。

      PS:这道题数据有错,它没有保证$q$一定能被异或出来

    Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef bool boolean;
     4 
     5 const int MAX_BASE = 31, M = 10086; 
     6 
     7 int qpow(int a, int pos) {
     8     int pa = a, rt = 1;
     9     for ( ; pos; pos >>= 1, pa = pa * pa % M)
    10         if (pos & 1)
    11             rt = rt * pa % M;
    12     return rt;
    13 }
    14 
    15 int n, q;
    16 int *ar;
    17 int b[MAX_BASE];
    18 int s[MAX_BASE];
    19 
    20 inline void init() {
    21     scanf("%d", &n);
    22     ar = new int[(n + 1)];
    23     for (int i = 1; i <= n; i++)
    24         scanf("%d", ar + i);
    25     scanf("%d", &q);
    26 }
    27 
    28 int cnt = 0, rk = 0;
    29 inline void solve() {
    30     for (int i = 1; i <= n; i++) {
    31         for (int j = MAX_BASE - 1; ~j; j--) {
    32             if (ar[i] & (1 << j))    ar[i] ^= b[j]; 
    33             if (ar[i] & (1 << j)) {
    34                 b[j] = ar[i];
    35                 cnt++;
    36                 break;
    37             }
    38         }
    39     }
    40     for (int i = 0; i < MAX_BASE; i++)
    41         if (b[i])
    42             s[i] = 1;
    43     for (int i = 0; i < MAX_BASE; i++)
    44         s[i] += s[i - 1];
    45     for (int i = MAX_BASE - 1; ~i; i--)
    46         if ((q & (1 << i)) && b[i])
    47             rk |= (1 << (s[i] - 1));
    48     printf("%d
    ", ((rk % M) * qpow(2, n - cnt) + 1) % M);
    49 }
    50 
    51 int main() {
    52     init();
    53     solve();
    54     return 0;
    55 }
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8502941.html
Copyright © 2011-2022 走看看