正题
题目大意
n n n个数,对于每个数找左边的一个数执行 o p t opt opt操作使得答案最大,并且求有多少个数能够使得最大。
解题思路
我们设 f i , j f_{i,j} fi,j表示下一个数的后 8 8 8位为 i i i,当前数的前 8 8 8位为 j j j时的最大后 8 8 8位的答案。然后每次用 f i , b f_{i,b} fi,b统计完答案后更新 f a , i f_{a,i} fa,i即可。
时间复杂度 O ( n m ) O(n\sqrt m) O(nm)
c o d e code code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MS=1<<8;
int n,idx,f[MS][MS],g[MS][MS];
char op[8];
int main()
{
//freopen("binary.in","r",stdin);
//freopen("binary.out","w",stdout);
scanf("%d%s%d",&n,op,&idx);
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
int a=x&(MS-1),b=x>>8;
if(i>1){
int ans1=0,ans2=0;
for(int j=0;j<MS;j++){
int z;
if(!g[a][j])continue;
if(op[0]=='o')z=(j|b)<<8;
else if(op[0]=='x')z=(j^b)<<8;
else z=(j&b)<<8;
if(f[a][j]+z>ans1)ans1=f[a][j]+z,ans2=g[a][j];
else if(f[a][j]+z==ans1)ans2+=g[a][j];
}
printf("%d",ans1);
if(idx==1)printf(" %d",ans2);
putchar('\n');
}
for(int j=0;j<MS;j++){
int z;
if(op[0]=='o')z=j|a;
else if(op[0]=='x')z=j^a;
else z=j&a;
if(z>f[j][b])f[j][b]=z,g[j][b]=1;
else if(z==f[j][b])g[j][b]++;
}
}
}