• [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;
    }
    
    
  • 相关阅读:
    【转】C#解析HTML 拓荒者
    【转】Sql递归查询 拓荒者
    【转】sql if else 语句 拓荒者
    数据库范式解析 拓荒者
    C#和sqlserver中生成新的32位GUID 拓荒者
    Linq To Sql CRUD操作示例 拓荒者
    让UserControl可以被验证 拓荒者
    【转】把一个表的数据插入到另一个表:INSERT INTO SELECT / SELECT INTO 拓荒者
    【转】Sql去除重复记录 拓荒者
    Linq To Object 示例 拓荒者
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7643387.html
Copyright © 2020-2023  润新知