zoukankan      html  css  js  c++  java
  • BZOJ 4976 [Lydsy1708月赛]宝石镶嵌

    【题解】

      我们设总共有m个二进制位出现过1,那么如果n-k≥m,显然所有的1都可以出现,那么答案就是把所有的数或起来。

      如果n-k<m,那么因为k不超过100,ai不超过1e5,所以n不超过117,直接n*1e5的Dp即可。

      Dp的方式也是多种多样,如果设f[i][j]表示前i个数字或出j最少需要几个数字,那么转移方程为f[i][j|a[i]]=min(f[i-1][j|a[i]],f[i-1][j]+1]).

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long
     5 #define rg register
     6 #define N 131072
     7 using namespace std;
     8 int n,m,k,sum,ans,a[N],f[120][N];
     9 inline int read(){
    10     int k=0,f=1; char c=getchar();
    11     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    12     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    13     return k*f;
    14 }
    15 int main(){
    16     n=read(); k=read();
    17     for(rg int i=1;i<=n;i++) a[i]=read(),sum|=a[i];
    18     int x=sum;
    19     for(rg int i=16;i;i--)if(x>=(1<<i)) m++,x-=(1<<i);
    20     if(n-k>=m) printf("%d
    ",sum);
    21     else{
    22         for(rg int i=0;i<=n;i++)
    23             for(rg int j=0;j<N;j++) f[i][j]=n;
    24         f[0][0]=0;
    25         for(rg int i=1;i<=n;i++) {
    26             for(rg int j=0;j<N;j++)
    27             f[i][j|a[i]]=min(f[i][j|a[i]],f[i-1][j]+1); 
    28             for (rg int j=0;j<N;j++)
    29             f[i][j]=min(f[i][j],f[i-1][j]);
    30         }
    31         for(rg int i=0;i<N;i++) if(f[n][i]<=n-k) ans=i;
    32         printf("%d
    ",ans);
    33     }
    34     return 0;
    35 }
    View Code
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long
     5 #define rg register
     6 #define N 131072
     7 using namespace std;
     8 int n,m,k,sum,ans,a[N],f[120][N];
     9 inline int read(){
    10     int k=0,f=1; char c=getchar();
    11     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    12     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    13     return k*f;
    14 }
    15 int main(){
    16     n=read(); k=read();
    17     for(rg int i=1;i<=n;i++) a[i]=read(),sum|=a[i];
    18     int x=sum;
    19     for(rg int i=16;i;i--)if(x>=(1<<i)) m++,x-=(1<<i);
    20 //    printf("%d %d
    ",m,sum);
    21     if(n-k>=m) printf("%d
    ",sum);
    22     else{
    23         for(rg int i=0;i<=n;i++)
    24             for(rg int j=0;j<N;j++) f[i][j]=-n;
    25         f[0][0]=0;
    26         for(rg int i=1;i<=n;i++)
    27             for(rg int j=0;j<N;j++)
    28                 f[i][j]=max(f[i][j],f[i-1][j]+1),
    29                 f[i][j|a[i]]=max(f[i][j|a[i]],f[i-1][j]);
    30         for(rg int i=1;i<N;i++) if(f[n][i]>=k) ans=i;
    31         printf("%d
    ",ans);
    32     }
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    【006期】JavaSE面试题(六):泛型
    【005期】JavaSE面试题(五):String类
    【004期】JavaSE面试题(四):JavaSE语法(3)
    【003期】JavaSE面试题(三):JavaSE语法(1)
    【002期】JavaSE面试题(二):基本数据类型与访问修饰符
    【001期】 | JavaSE面试题(一):面向对象
    【000期】Java最全面试题库思维导图
    LeetCode 1. 两数之和(python3)实现
    虚拟网络学习笔记一:Linux虚拟网络
    快速排序(python实现)
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9761427.html
Copyright © 2011-2022 走看看