Loading

big

\(link\)

这道题暴力有\(40pts\),直接枚举选择的数和对手操作的时间按就行了

位运算最大的好处就是不进位,异或只和当前位有关
题目中的式子其实是循环左移一位(用\(opt\)表示)。
他让我们找一个\(x\),使得\(opt[(x\text{^}front_i)]\text{^}front_i\text{^}front_n\)
然后根据位运算的性质,可以把循环左移拆开。
\(y\)等于\(opt(x)\),可以知道\(y\)\(x\)是一一对应的。
问题就变成了找一个\(y\),使得\(y\text{^}opt[front_i]\text{^}front_i\text{^}front_n\)最大。
然后发现后面那堆东西可以预处理,那就搞出来之后都扔到\(tire\)树里面。
问题变成了,选择一个数,使最小异或值最大。
你的对手会让你的数尽量小,所以当当前节点有两个儿子的时候,你选1他也选1,你选0他也选0,所以没有贡献。
当只有一个儿子的时候,他是1你选0,他是0你选1,必定可以有贡献。
那就直接\(dfs\)一遍\(tire\)树就行了。

code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long
#define R register int
#define printf Ruusupuu = printf

using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned long long G ;
const int N = 1e5 + 10 ;

int Ruusupuu ;

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
	while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ '0' ) , ch = getchar() ;
	return fg ? -w : w ;
}

int n , m , k [N] , ans , lnt , num ;
int ch [N << 5][2] , tot = 1 ;

void sc(){
	n = read() , m = read() ;	
	for( R i = 1 ; i <= m ; i ++ ) k [i] = read() , k [i] ^= k [i - 1] ;
}

inline void ins( int x ){
	int t = 1 ;
	for( R i = n - 1 ; i >= 0 ; i -- ){
		int c = ( x >> i ) & 1 ;
	//	printf( "%ld %ld %ld\n" , x , i , c ) ;
		if( !ch [t][c] ) ch [t][c] = ++ tot ; 
		t = ch [t][c] ;//printf( "%ld %ld\n" , tot , t ) ; 
	}
}

inline void dfs( int x , int num , int cnt ){
	if( cnt == 0 ){
		if( num > ans ) ans = num , lnt = 1 ;
		else if( num == ans ) lnt ++ ;	
		return ; 
	} 
	if( ch [x][0] && ch [x][1] )
		dfs( ch [x][0] , num , cnt - 1 ) , dfs( ch [x][1] , num , cnt - 1 ) ;
	else if( ch [x][0] || ch [x][1] ) dfs( ch [x][0] + ch [x][1] , num + ( 1 << ( cnt - 1 ) ) , cnt - 1 ) ;
}

void work(){
	for( R i = 0 ; i <= m ; i ++ ){
		int ams = k [i] ; int t = ams >> ( n - 1 ) ;
		t += ams << 1 ; t %= ( 1 << n ) ;
		t ^= k [i] , t ^= k [m] ;	
		ins( t ) ; 
 	}	dfs( 1 , 0 , n ) ;
 	printf( "%ld\n%ld\n" , ans , lnt ) ;
		
}

signed main(){	
	sc() ;
	work() ;
	return 0 ;
}
posted @ 2021-06-09 08:00  Soresen  阅读(103)  评论(0)    收藏  举报