zoukankan      html  css  js  c++  java
  • CF1163E Magical Permutation

    题意:给定集合,求一个最大的x,使得存在一个0 ~ 2x - 1的排列,满足每相邻的两个数的异或值都在S中出现过。Si <= 2e5

    解:若有a,b,c,令S1 = a ^ b, S2 = b ^ c,则有a ^ c = S1 ^ S2

    因为有0存在,所以每个数都能表示成它到0路径上的所有间隔的异或和,也就是每个数都能被表示出来。我们用线性基来判断。

    找到最大的x之后,我们可以发现,线性基中x个数的2x种选法一一对应这2x个数。于是直接采用格雷码来找这个排列,每加一位,就在x个数中添加 / 删除一个数到异或集合中。

    我的实现较复杂。实际上只要把线性基这x个数记下来,格雷码的时候选择是否异或即可。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 500010;
     4 
     5 int n, a[N], base[64], T, id[64], sta[N], pos[N], s;
     6 
     7 inline void clear() {
     8     memset(base, 0, sizeof(base));
     9     memset(id, 0, sizeof(id));
    10     return;
    11 }
    12 
    13 inline void insert(int x, int v) {
    14     int V = 0;
    15     for(int i = T - 1; i >= 0; i--) {
    16         if(!((x >> i) & 1)) {
    17             continue;
    18         }
    19         if(base[i]) {
    20             x ^= base[i];
    21             V ^= id[i];
    22         }
    23         else {
    24             base[i] = x;
    25             id[i] = V | (1 << i);
    26             break;
    27         }
    28     }
    29     return;
    30 }
    31 
    32 inline bool check() {
    33     for(int i = T - 1; i >= 0; i--) {
    34         if(!base[i]) {
    35             return false;
    36         }
    37     }
    38     return true;
    39 }
    40 
    41 inline void find(int x) {
    42     int t = x;
    43     for(int i = T - 1; i >= 0; i--) {
    44         if(!((x >> i) & 1)) {
    45             continue;
    46         }
    47         x ^= base[i];
    48         sta[t] ^= id[i];
    49     }
    50     return;
    51 }
    52 
    53 void DFS(int k) {
    54     if(k == -1) {
    55         printf("%d ", pos[s]);
    56         return;
    57     }
    58     DFS(k - 1);
    59     s ^= 1 << k;
    60     DFS(k - 1);
    61     return;
    62 }
    63 
    64 int main() {
    65     scanf("%d", &n);
    66     for(int i = 1; i <= n; i++) {
    67         scanf("%d", &a[i]);
    68     }
    69     std::sort(a + 1, a + n + 1);
    70     int fin = 0;
    71     for(T = 0; T <= 18; T++) {
    72         int lm = (1 << T) - 1;
    73         clear();
    74         for(int i = 1; i <= n && a[i] <= lm; i++) {
    75             insert(a[i], i);
    76         }
    77         if(check()) {
    78             fin = T;
    79         }
    80     }
    81     T = fin;
    82     /// T 
    83     int lm = (1 << T) - 1;
    84     for(int i = 1; i <= lm; i++) {
    85         find(i);
    86         pos[sta[i]] = i;
    87     }
    88     printf("%d
    ", T);
    89     DFS(T - 1);
    90     puts("");
    91     return 0;
    92 }
    AC代码
  • 相关阅读:
    Saltstack module acl 详解
    Saltstack python client
    Saltstack简单使用
    P5488 差分与前缀和 NTT Lucas定理 多项式
    CF613D Kingdom and its Cities 虚树 树形dp 贪心
    7.1 NOI模拟赛 凸包套凸包 floyd 计算几何
    luogu P5633 最小度限制生成树 wqs二分
    7.1 NOI模拟赛 dp floyd
    springboot和springcloud
    springboot集成mybatis
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/11097417.html
Copyright © 2011-2022 走看看