zoukankan      html  css  js  c++  java
  • CF981D Bookshelves

    按位贪心+DP的好题qwq

    首先看到题目的要求,统计价值的时候的操作是按位与,就要有按位分别计算的意识

    开始没意识到结果想了好久还是看了题解才想到

    由于统计价值的方式不是加和,所以可能会出现两个较大的值AND起来更小甚至变成0,所以不能直接DP

    考虑按位贪心

    显然高位为1后的值一定比高位不为1的值要大,所以从高位向下贪心,每次检查能否在使前i个位值不变的情况下,使新加入的位变为1

    检查的时候用区间dp实现即可

    (dp[i][j])表示前j本书分到前i个书架上是否能使前面的位不变且当前检查的位为1

    状态转移方程为:

    dp[i][j]|=dp[i-1][kx]&&(((sum[j]-sum[kx])&&x)==x) 
    

    总的复杂度是(O(n^{2}k))

    注意位运算优先级和枚举的最高位的位数

    代码

    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define int long long
    using namespace std;
    int n,k,a[51],sum[51],dp[51][51],ans=0;
    int check(int x){
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=1;i<=k;i++)
            for(int j=1;j<=n;j++)
                for(int kx=0;kx<j;kx++)
                    dp[i][j]|=dp[i-1][kx]&&(((sum[j]-sum[kx])&x)==x);
        return dp[k][n];
    }
    signed main(){
        scanf("%lld %lld",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+a[i];
        for(int i=60;i>=0;i--){
            int mid=ans|(1LL<<i);
            if(check(mid))
                ans|=(1LL<<i);
        }
        printf("%lld",ans);
        return 0;
    }
    
    
  • 相关阅读:
    java keytool证书工具使用小结(转)
    Https socket 代理
    SSL连接出现的问题
    Https 代理 sslsocket
    Https socket 连接
    linux系统一键安装phpstudy的lnmp环境
    Yii2框架实现计数器功能
    yii2框架增删改查案例
    yii2框架原生的结合框架使用的图片上传
    php将抓取的图片链接下载到本地
  • 原文地址:https://www.cnblogs.com/dreagonm/p/9890518.html
Copyright © 2011-2022 走看看