zoukankan      html  css  js  c++  java
  • P4574 [CQOI2013]二进制A+B 题解(数位dp)

    题目链接

    题目思路

    想不到居然是数位dp

    \(dp[i][j][k][u][0/1]\)

    表示枚举到第\(i\)位,\(a\)用了\(j\)个1,\(b\)用了\(k\)个1,\(c\)用了\(u\)个1,以及最后一位是否进位

    这个dp转移有点阴间 要好好理解才能明白其中的细节

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    #define fi first
    #define se second
    #define debug printf("aaaaaaaaaaa\n");
    const int maxn=30+5,inf=0x3f3f3f3f,mod=1e9+7;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int n;
    int a,b,c;
    int numa,numb,numc;
    ll dp[maxn][maxn][maxn][maxn][2];
    int get(int x){
        int cnt=0;
        while(x){
            if(x&1) cnt++;
            x/=2;
        }
        return cnt;
    }
    int main(){
        memset(dp,0x3f,sizeof(dp));
        cin>>a>>b>>c;
        numa=get(a),numb=get(b),numc=get(c);
        n=max({(int)log2(a)+1,(int)log2(b)+1,(int)log2(c)+1});
        dp[0][0][0][0][0]=0;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=numa;j++){
                for(int k=0;k<=numb;k++){
                    for(int u=0;u<=numc;u++){
                        ll add=dp[i][j][k][u][0];
                        dp[i+1][j+1][k+1][u+1][1]=min(dp[i+1][j+1][k+1][u+1][1],add+(1<<i+1));
                        dp[i+1][j][k+1][u+1][0]=min(dp[i+1][j][k+1][u+1][0],add+(1<<i));
                        dp[i+1][j+1][k][u+1][0]=min(dp[i+1][j+1][k][u+1][0],add+(1<<i));
                        dp[i+1][j][k][u][0]=min(dp[i+1][j][k][u][0],add);
                        add=dp[i][j][k][u][1];
                        dp[i+1][j+1][k+1][u+1][1]=min(dp[i+1][j+1][k+1][u+1][1],add+(1<<i+1));
                        dp[i+1][j][k+1][u][1]=min(dp[i+1][j][k+1][u][1],add+(1<<i));
                        dp[i+1][j+1][k][u][1]=min(dp[i+1][j+1][k][u][1],add+(1<<i));
                        dp[i+1][j][k][u][0]=min(dp[i+1][j][k][u][0],add);
                    }
                }
            }
        }
        ll ans=dp[n][numa][numb][numc][0];
        if(ans>=INF) ans=-1;
        cout<<ans<<'\n';
        return 0;
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    runtime-给系统已有类添加属性
    解决自定义leftBarButtonItem返回手势失效的方法
    类和对象
    内存拷贝
    响应者链
    属性
    懒加载
    封装思想
    屏幕旋转
    block
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15020353.html
Copyright © 2011-2022 走看看