首页 > 代码库 > hihocoder 1496:寻找最大值(高维前缀最大次大值)

hihocoder 1496:寻找最大值(高维前缀最大次大值)

 

【题目链接】 https://hihocoder.com/problemset/problem/1496

 

【题目大意】

  给定N个数A1, A2, A3, ... AN,
  从中找到两个数Ai和Aj(i≠j)使得乘积Ai*Aj*(Ai&Aj)最大

 

【题解】

  我们可以枚举x&y的结果z,找出两个数x&y==z使得x*y最大,更新答案即可,
  条件可以被削弱为z为x&y的子集,这种条件放缩不会导致最优解的丢失,
  z为x&y的子集等价于z为x的子集并且z为y的子集。
  那么我们只要找出以z为子集的最大值和次大值,然后枚举z即可计算出答案。
  复杂度O(k*2^k).

 

【代码】

#include <cstdio>#include <algorithm>using namespace std;struct data{    int val[2];    data operator +(const data &rhs)const{        int t_val[2]={val[0],val[1]};        for(int i=0;i<2;i++){            if(rhs.val[i]>t_val[0]){                t_val[1]=t_val[0];                t_val[0]=rhs.val[i];            }else if(rhs.val[i]>t_val[1])t_val[1]=rhs.val[i];        }return data{t_val[0],t_val[1]};    }}dp[(1<<20)+10];int T,n;int main(){    scanf("%d",&T);    int all=1<<20;    while(T--){        for(int i=0;i<all;i++)dp[i]=data{0,0};        scanf("%d",&n);        for(int i=1,x;i<=n;i++){            scanf("%d",&x);            dp[x]=dp[x]+data{x,0};        }         for(int i=0;i<20;i++)            for(int j=0;j<all;j++)                if(~j&(1<<i))dp[j]=dp[j]+dp[j|(1<<i)];        long long ans=0;        for(int i=0;i<all;i++)ans=max(ans,1LL*i*dp[i].val[0]*dp[i].val[1]);        printf("%lld\n",ans);    }return 0;}

hihocoder 1496:寻找最大值(高维前缀最大次大值)