二进制的世界
二进制的世界
题解
有趣的做法,准确说是我太菜了, 
      
       
        
        
          S 
         
        
          Y 
         
        
          D 
         
        
          e 
         
        
          v 
         
        
          i 
         
        
          l 
         
        
       
         SYDevil 
        
       
     SYDevil大佬秒切了
我们可以考虑对于每个数二进制分段。
 由于 
     
      
       
        
        
          a 
         
        
          i 
         
        
       
         < 
        
        
        
          2 
         
        
          16 
         
        
       
      
        a_{i}< 2^{16} 
       
      
    ai<216,所以我们可以记录下 
     
      
       
       
         d 
        
        
        
          p 
         
         
         
           i 
          
         
           , 
          
         
           j 
          
         
        
       
      
        dp_{i,j} 
       
      
    dpi,j表示前 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位为 
     
      
       
       
         i 
        
       
      
        i 
       
      
    i的数的后八位与 
     
      
       
       
         j 
        
       
      
        j 
       
      
    j进行操作可以得到的后八位最大值。
 由于这些数前 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位是一样的,所以当这些数与某个数进行操作后,前 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位都是一样的,它们不同的地方在后 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位,而这后 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位有是与另一个数的后 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位进行操作的,所以我们只需要固定另外一个数的后 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位,就可以知道所有前 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位为 
     
      
       
       
         i 
        
       
      
        i 
       
      
    i的数与这个数进行操作的最大值。
 而对于每个数,它自身的后 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位是固定的,我们只需要枚举它的前 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位与哪个数进行操作。
 同理,当它加入 
     
      
       
       
         d 
        
       
         p 
        
       
      
        dp 
       
      
    dp答案时,我们也只需要枚举它的后 
     
      
       
       
         8 
        
       
      
        8 
       
      
    8位与哪个数进行操作,加入 
     
      
       
       
         d 
        
       
         p 
        
       
      
        dp 
       
      
    dp状态。
很明显,我们对于每个数会进行 2 8 2^8 28次操作,所以时间复杂度是 O ( n a ) O\left(n\sqrt{a}\right) O(na)的。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;       
const LL INF=0x3f3f3f3f;       
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int lim=1e9;
const int n1=150;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
const int M=MAXN/n1+5;
int n,typ,a[MAXN],dp[260][260],cnt[260][260],op;
char opt[10];
inline int work(int x,int y){return (op==1)?(x&y):((op==2)?(x|y):(x^y));}
signed main(){
	scanf("%d %s",&n,opt+1);
	if(opt[1]=='a')op=1;else if(opt[1]=='o')op=2;else op=3;
	for(int i=1;i<=n;i++)read(a[i]);
	for(int i=1;i<=n;i++){
		int maxx=0,res=0,S1=a[i]>>8,S2=a[i]&((1<<8)-1);
		if(i>1)for(int j=0;j<(1<<8);j++)if(cnt[j][S2]){
			int tmp=(work(S1,j)<<8)|dp[j][S2];
			if(tmp>maxx)maxx=tmp,res=0;
			if(tmp==maxx)res+=cnt[j][S2];
		}
		for(int j=0;j<(1<<8);j++){
			int tmp=work(S2,j);
			if(tmp>dp[S1][j])dp[S1][j]=tmp,cnt[S1][j]=0;
			if(dp[S1][j]==tmp)cnt[S1][j]++;
		}
		if(i>1)printf("%d %d\n",maxx,res);
	}
	return 0;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号