zoukankan      html  css  js  c++  java
  • BZOJ_2844 albus就是要第一个出场 【线性基】

    一、题目

      albus就是要第一个出场

    二、分析

      非常有助于理解线性基的一题。

      构造线性基$B$后,如果$|A| > |B|$,那么就意味着有些数可以由$B$中的数异或出来,而多的数可以取或者不取,相当于每多一个数,那么线性基能生成的数的子集的种类就可以乘以$2$,最终就是乘以$2^{|A|-|B|}$。

      所以对于给定的$Q$,要确定它是由哪些位置的线性基中的数生成的,然后确定它在不重复序列中的位置,然后再乘以$2^{|A|-|B|}$,最终还需要$+1$,因为前面求的其实是不包含这个数的子集总个数。

    三、AC代码

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 #define ll long long
     5 #define Min(a,b) ((a)>(b)?(b):(a))
     6 #define Max(a,b) ((a)>(b)?(a):(b))
     7 const int MAXN = 1e5 + 13;
     8 const int MAXL = 30;
     9 const int mod = 10086;
    10 int base[MAXL + 2];
    11 
    12 int Pow(int a, int b)
    13 {
    14     int ans = 1;
    15     while(b) {
    16         if(b & 1)   ans = ans * a % mod;
    17         b >>= 1;
    18         a = a * a % mod;
    19     }
    20     return ans;
    21 }
    22 
    23 
    24 int main()
    25 {
    26     //freopen("input.txt", "r", stdin);
    27     //freopen("out.txt", "w", stdout);
    28     int n, a, cnt = 0, q;
    29     scanf("%d", &n);
    30     memset(base, 0, sizeof(base));
    31     for(int i = 0; i < n; i++) {
    32         scanf("%d", &a);
    33         for(int j = MAXL; j >= 0; j--) {
    34             if(a & (1<<j)) {
    35                 if(base[j])
    36                     a ^= base[j];
    37                 else {
    38                     base[j] = a;
    39                     for(int k = j - 1; k >= 0; k--) {
    40                         if(base[j] & (1<<k) )
    41                             base[j] ^= base[k];
    42                     }
    43                     for(int k = j + 1; k <= MAXL; k++) {
    44                         if(base[k] & (1<<j) )
    45                             base[k] ^= base[j];
    46                     }
    47                     cnt++;
    48                     break;
    49                 }
    50             }
    51         }
    52     }
    53     scanf("%d", &q);
    54     vector<int> pos;
    55     int p = 0, res = 0;
    56     for(int i = 0; i <= MAXL; i++) {
    57         if(base[i]) pos.push_back(i);
    58     }   
    59     for(int i = 0; i < pos.size(); i++) {
    60         if(q>>pos[i] & 1) {
    61             res += (1<<i);
    62         }
    63     }
    64     printf("%d
    ", (res % mod * Pow(2, n - cnt) % mod + 1)%mod );
    65     return 0;
    66 }
  • 相关阅读:
    nexus搭建maven私服
    eclipse 使用git
    多启动引导工具_YUMI – Multiboot USB Creator
    减压Zip与创建Zip文档
    将设置集成到右键联级菜单
    在Windows 10上清除和管理TPM (受信任的平台模块)
    删除Windows运行记录
    计算文本HasH
    在右键新建中添加"Windows PowerShell脚本"
    调整Windows 10字号
  • 原文地址:https://www.cnblogs.com/dybala21/p/11366783.html
Copyright © 2011-2022 走看看