• 【bzoj4976】宝石镶嵌(思维dp)


      题目传送门:bzoj4976

      不得不说这是道脑洞dp,思路真的清奇。

      我们可以发现,虽然n很大,但是k只有100,这里面似乎隐藏了什么玄机。

      我们可以发现,设总共有$ tot $个二进制位在这n个数中有出现过1,那么当$ n-k>=tot $时,所有二进制位都能取到,可以直接计算答案。

      当$ n-k<tot $时,n最大只有116(因为宝石价值最大只有1e5<2^17),那么就可以随便dp一下:设$ f[i][j] $表示处理前$ i $个数,当前或运算结果为$ j $时,最多能选取多少个数,那么就可以得到:$ f[i][j|w[i]]=max(f[i][j|w[i]],f[i-1][j]+1) $

      代码:

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define maxn 100010
    int a[maxn],f[180010];
    int n,k;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline void read(int &x)
    {
        x=0; char c=nc();
        for(;c<'0'||'9'<c;c=nc());
        for(;'0'<=c&&c<='9';c=nc())x=(x<<3)+(x<<1)+c-'0';
    }
    int main()
    {
        read(n); read(k);
        int mx=0;
        for(int i=1;i<=n;i++){
            read(a[i]);
            if(a[i]>mx)mx=a[i];
        }
        int tot=0,tmp=0,hhh=0;
        for(int i=1;i<=mx;i<<=1,++hhh){
            int flag=0;
            for(int j=1;j<=n;j++)
                if(a[j]&i){
                    flag=1; break;
                }
            if(flag)++tot,tmp|=i;
        }
        if(n-k>=tot){
            printf("%d
    ",tmp); return 0;
        }
        for(int i=0;i<(1<<hhh);i++)f[i]=0x3f3f3f3f; f[0]=0;
        for(int i=1;i<=n;i++)
            for(int j=(1<<hhh)-1;j>=0;j--)
                if(f[j]+1<f[j|a[i]])f[j|a[i]]=f[j]+1;
        int ans=0;
        for(int i=0;i<(1<<hhh);i++)
            if(f[i]+k<=n&&ans<i)ans=i;
        printf("%d
    ",ans);
    }
    bzoj4976
  • 相关阅读:
    Vue常用语法
    Vue--过滤器、指令、插件
    使用vue-cli创建项目
    electron Ctrl+滚轮事件 放大缩小
    axios 处理超时问题 记录
    electron 清除所有cookie记录
    electron用默认浏览器打开链接的3种实现方式
    electron 不支持Ctrl+滚动条放大缩小,自己动手做了一个react组件
    排序算法记录
    umi react 集成 spreadjs
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/10078815.html
Copyright © 2020-2023  润新知