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
  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9761427.html
Copyright © 2011-2022 走看看