big(某trie树题)

2x <  2^(n+1),所以2x /  2^n 不是1就是0,2x  %  2^n,就是第n位为0.

2x最多n位,其实就是把2x的最高位移到最后一位。这个操作简称左移。

其实所有数异或起来再左移和左移以后再异或是一样的。。。

对手可以把x左移的时刻有m+1个。(0,1,2,3....m)

如果对手把x 在i时刻左移。

就相当与把a1 - ai个数左移以后异或的值再异或ai+1 到am;

所以这m+1个时刻,可以看成m+1个x可以异或的数。

第i个数等于a1 - ai个数左移以后异或的值再异或ai+1 到am。

然后把这m+1个数建一个trie数,

就相当与找一个数x与m+1个数分别异或的最小值最大。

从上往下dfs,想要结果最优。

如果trie上某个节点有1,0两个儿子,我们的x无论这一位取1还是0,都不能产生贡献(异或,相同为0)。两个儿子,dfs下去。如果这个节点只有1 一个儿子,那么我们让x这一位取0.  向儿子1,dfs下去。

如果这个节点只有0 一个儿子,那么我们让x这一位取1.   向儿子0,dfs下去。

如果到叶子节点,ans 大于已知最大值,把最大值赋为ans,个数等于1;

如果到叶子节点,ans 等于于已知最大值,个数加1;

#include<bits/stdc++.h>
using namespace std;
int a[100005], b[100005], ha[100005], he, tot, ans1, tr[2000005][2], ma;
void read(int &x)
{
	x = 0;   int f  = 0;  char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-') f = 1;   c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		x = 10 * x + c - '0';   c = getchar();
	}
	if(f) x = -x;
}
int n,m;
int zhuan(int x)
{
  x = x << 1;
   if(x >> n & 1)
   {
   	x ^= he;   x += 1;
   }
  // int hehe = (long long)(x << 1) / he;
   //int haha = (long long)hehe + ((he - 1) & (x << 1));
   return x; 
}
void build(int x)
{
	int nd = 0;
	for(int i = n-1; i >= 0; i-- )
   {
   	  int haha = (x >> i) & 1;
   	  if(tr[nd][haha] == 0)
   	  	tr[nd][haha] = ++tot;
   	  nd = tr[nd][haha];
   }
}
void dfs(int nd, int dep, int ans)
{
	if(dep == -1)
	{
		if(ans > ma)
		{
			ma = ans;   ans1 = 1;
		}
		else if(ans == ma)  ans1++;
		return ;
	}	
	if(tr[nd][1] != 0 && tr[nd][0] != 0)
	{
	      dfs(tr[nd][0],dep-1,ans); dfs(tr[nd][1],dep-1,ans);
	}
	else if(tr[nd][1] != 0)
		dfs(tr[nd][1], dep-1, ans + (1 << dep));
else
		dfs(tr[nd][0], dep-1, ans + (1 << dep));

}
int main()
{
	//freopen("big.in","r",stdin);
	//freopen("big.out","w",stdout);
   read(n); read(m);	
    he = 1 << n;
   for(int i = 1; i <= m; i++)
   {
   	read(a[i]);  
   }	
   for(int i = m; i >= 1; i--)
   ha[i] = ha[i+1] ^ a[i];
   for(int i = 1; i <= m; i++)
   {
   	a[i] = a[i] ^ a[i-1];
    b[i] = zhuan(a[i]); 
   }
   for(int i = 0; i <= m; i++)
   	b[i] = b[i] ^ ha[i+1];
   for(int i = 0; i <= m; i++)
   
   {
 
       build(b[i]);}
   int nd = 0;
    dfs(0,n-1,0);
   cout << ma << endl;
   cout << ans1 << endl;
   return 0;
} 

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/83512909