ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP 模拟5 T3 big

2021-06-08 12:02:05  阅读:200  来源: 互联网

标签:NOIP trie big 左移 T3 异或 MAXM swr define


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

     对于 20%的数据,n<=10,m<=100。
     对于 40%的数据,n<=10,m<=1000。
     对于另外 20%的数据,n<=30,m<=10。
     对于 100%的数据 n<=30,m<=100000,0<=ai<2^n。

考场上拿到这道题是很懵的 问题在于对于异或的理解应用 实质上是对于一些基础性问题的理解并不深入

  分析问题 值得注意的是  我们很显然需要理解这个式子在说什么

观察式子结构 应该能明确用二进制视角剖析 因此很简单 2X表示X左移一位 2^n表示X右移n位 综合来说就是将X首位放到了末尾

显然模2^n的结果不变 而2X模2^n相当与左移一位后删除首位 配合上述,我们可以得出结论 原式实际上是对X的逻辑左移

  继续考虑 为了将结论应用到解题中 我们显然要分析原式与异或运算体系的关联

异或运算的一个重要特点是位与位之间的运算是相互独立的互补影响 由此很容易推出a ^ (b << 1) = (a << 1) ^ b (其中<<代表逻辑左移)

  接下来思路就很清晰l 因为同时考虑x的选择和左移十分复杂 因此我们转而考虑a[]的左移 可以预处理出a[]的前缀和(逻辑左移)与后缀和

目标是最大异或和 显然这是一道Trie树模板题 存储0,1字符串进行抉择

  值得一提的是“而你的对手会使 x 最后尽量小”这就是说同时存在0,1两种选择则无法对结果造成贡献

若仅存在一种选择 则取反进行选择 代码用dfs深搜枚举可能情况即可

 

 1 #include<bits/stdc++.h>    
 2 using namespace std;            
 3 #define I int
 4 #define C char
 5 #define RE register
 6 #define V void
 7 #define L inline                                  
 8 const I MAXM =  100050;
 9 I n,m,mod,num,res,swr,tot,a[MAXM],qa[MAXM],ha[MAXM],trie[MAXM << 5][2],l[MAXM << 5],r[MAXM << 5];
10 L I read(); L I fir(I); L V ins(I); V dfs(I,I); 
11 signed main(){
12     n = read(); m = read(); mod = 1 << n;
13     for(RE I i(1);i <= m; ++ i) a[i] = read();
14     for(RE I i(1);i <= m; ++ i) qa[i] = qa[i - 1] ^ fir(a[i]);
15     for(RE I i(m); i ; -- i)      ha[i] = ha[i + 1] ^ a[i];
16     for(RE I i(0);i <= m; ++ i) ins(qa[i] ^ ha[i + 1]);
17     dfs(0,n - 1);    
18     printf("%d\n%d",res,num);       
19 }
20 L I read(){  RE I x(0);RE C z = getchar(); while(!isdigit(z)) z = getchar(); while(isdigit(z)) x = (x << 3) + (x << 1) + (z ^ 48),z = getchar(); return x;  }
21 L I fir(I a){  return ((a >> n - 1) | (a << 1)) % mod;  }
22 L V ins(I a){   I p(0);
23     for(RE I i(n - 1),t;i >= 0; -- i){
24         t = a >> i & 1;
25         if(!trie[p][t]) trie[p][t] = ++tot,t ? l[p] = tot : r[p] = tot;
26         p = trie[p][t];
27     }
28 }
29 V dfs(I from,I t){
30     if(!trie[from][1] && !trie[from][0]){
31       if(swr == res)    num++;
32         if(swr > res)   res = swr,num = 1;
33     }
34     if(trie[from][1] && !trie[from][0])     swr |= 1 << t,dfs(l[from],t - 1),swr ^= 1 << t;
35     if(!trie[from][1] && trie[from][0])     swr |= 1 << t,dfs(r[from],t - 1),swr ^= 1 << t;
36     if(trie[from][1] && trie[from][0])      dfs(l[from],t - 1),dfs(r[from],t - 1);
37 }
View Code

 

标签:NOIP,trie,big,左移,T3,异或,MAXM,swr,define
来源: https://www.cnblogs.com/WYZG/p/14862229.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有