zoukankan      html  css  js  c++  java
  • [10.9模拟] big

    题意:

    你需要在([0,2^n))中选一个整数 x,接着把 x 依次异或 m 个整数([a_1,a_m])
    在你选出 x 后,你的对手需要选择恰好一个时刻(刚选完数时、异或一些数后或是最后),将 x 变为(( 2x/2^n+2x) pmod {2^n})
    你想使 x 最后尽量大,而你的对手会使 x 最后尽量小
    你需要求出 x 最后的最大值,以及得到最大值的初值数量

    题解:

    trie树+贪心

    可以发现那个操作就是将二进制位上的数往前转一格,而由于异或每一位上的独立性,在每个时刻对手进行操作时,就相当于前面所有的数往前转一格再异或后面所有的数,即异或一个数

    所以我们可以O(m)的枚举断点,然后把每一个要异或的那个数加入到trie树中去

    最后在trie树上dfs一遍,如果当前位有0,1两个儿子,那么对手就一定可以把这一位搞成0,否则这一位一定能被你搞成1,于是你就可以得出那些位能产生贡献(即一定能选1),然后统计最大值,和达到最大值的方案即可

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define M 100010
    using namespace std;
    
    int n,m,sum,bin,id,tot,cnt;
    int ch[M*30][2],a[M],b[M],suf[M],t[50],ans[M];//ch数组大小为mlog,至多有m条链,每条链上至多n个结点
    
    int gi() {
      int x=0,o=1; char ch=getchar();
      while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
      if(ch=='-') o=-1,ch=getchar();
      while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
      return o*x;
    }
    
    void insert(int x) {
      for(int i=0; i<n; i++) t[i]=((x>>(n-i-1))&1);
      int u=0;
      for(int i=0; i<n; i++)  {
        if(!ch[u][t[i]]) ch[u][t[i]]=++id;
        u=ch[u][t[i]];
      }
    }
    
    void dfs(int u, int now, int lev) {
      if(lev<0) {
        ans[++cnt]=now;return;
      }
      if(ch[u][0] && !ch[u][1]) dfs(ch[u][0],now^(1<<lev),lev-1);
      if(ch[u][1] && !ch[u][0]) dfs(ch[u][1],now^(1<<lev),lev-1);
      if(ch[u][0] && ch[u][1]) {
        dfs(ch[u][0],now,lev-1);
        dfs(ch[u][1],now,lev-1);
      }
    }
    
    int main() {
      n=gi(),m=gi(),bin=1<<n;
      for(int i=1; i<=m; i++) a[i]=gi();
      for(int i=m; i>=1; i--) suf[i]=suf[i+1]^a[i];
      for(int i=0; i<=m; i++) {
        sum^=a[i];
        b[i]=((sum*2/bin)+2*sum)%bin^suf[i+1];
        insert(b[i]);
      }
      dfs(0,0,n-1);
      sort(ans,ans+cnt+1);
      for(int i=cnt; i>=1; i--) {
        if(ans[i]==ans[cnt]) tot++; 
      }
      printf("%d
    %d
    ", ans[cnt],tot);
      return 0;
    }
    
    
  • 相关阅读:
    CentOS7.6配置ip
    查看当前用户下没有主键也没有唯一性索引的表
    C++ 开机自动启动
    C++ 判断是文件还是文件夹
    Duilib热键
    c++将字符转换成字符串
    duilib中各控件响应的消息类型
    Duilib程序添加托盘图标显示
    C++打开文件夹
    C++获取驱动盘句柄
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7643387.html
Copyright © 2011-2022 走看看