zoukankan      html  css  js  c++  java
  • Luogu P1633 二进制

    题目大意 

      有三个整数$A$、$B$、$C$,以下用$N_{(2)}$表示$N$的二进制(没有前导$0$)。

      设$A_{(2)}$、$B_{(2)}$、$C_{(2)}$的最大长度为$L$($L leqslant 30$),你需要构造三个正整数$X$、$Y$、$Z$,满足以下条件:

      (1) $X_{(2)}$、$Y_{(2)}$、$Z_{(2)}$的长度都不超过$L$。

      (2) $A_{(2)}$与$X_{(2)}$中$1$的个数相同。

      (3) $B_{(2)}$与$Y_{(2)}$中$1$的个数相同。

      (4) $C_{(2)}$与$Z_{(2)}$中$1$的个数相同。

      (5) $X+Y=Z$。

      给你$A$,$B$,$C$,你需要求出最小的满足条件的$Z$。如果不存在满足条件的$Z$,那么输出$-1$。

    题解

      我们设$dp[i][a][b][c][j]$表示当前$X_{(2)}$和$Y_{(2)}$的最大长度为$i$,$Z_{(2)}$的最大长度为$i + 1$,$X_{(2)}$、$Y_{(2)}$、$Z_{(2)}$中$1$的个数分别为$a$、$b$、$c$,满足$X + Y = Z$的最小的$Z$,且$Z_{(2)}$的第$i + 1$位(最高位)为$j$。

      对于$dp[i][a][b][c][j]$,我们只需要枚举$X_{(2)}$、$Y_{(2)}$、$Z_{(2)}$的第$i + 1$位分别为什么,就可以更新$dp[i + 1][a'][b'][c'][j']$的值。最后输出的自然是$dp[L][Count(A_{(2)})][Count(B_{(2)})][Count(C_{(2)})][0]$($Count(A_{(2)})$表示$A_{(2)}$中$1$的个数,其他同)。

    #include <iostream>
    #include <cstring>
    
    #define LENGTH (30 + 5)
    #define INF 0x7f7f7f7f7f7f7f7f
    
    using namespace std;
    
    int T;
    int a, b, c;
    int cnta, cntb, cntc;
    long long dp[LENGTH][LENGTH][LENGTH][LENGTH][2]; 
    
    int Count(int x)
    {
        int cnt = 0;
        while(x)
        {
            cnt += x & 1;
            x >>= 1; 
        }
        return cnt;
    }
    
    int main()
    {
        cin >> T;
        int len, tmp;
        while(T--) 
        {
            cin >> a >> b >> c;
            cnta = Count(a);
            cntb = Count(b);
            cntc = Count(c);
            len = 0;
            tmp = 1;
            while(tmp <= a || tmp <= b || tmp <= c) tmp <<= 1, ++len;
            memset(dp, 0x7f, sizeof dp);
            dp[0][0][0][0][0] = 0;
            for(register int i = 0; i <= len; ++i)
            {
                for(register int ca = 0; ca <= i && ca <= cnta; ++ca)
                {
                    for(register int cb = 0; cb <= i && cb <= cntb; ++cb)
                    {
                        for(register int cc = 0; cc <= i && cc <= cntc; ++cc)
                        {
                            for(register int j = 0; j <= 1; ++j)
                            {
                                for(register int ba = 0; ba <= 1; ++ba)
                                {
                                    for(register int bb = 0; bb <= 1; ++bb)
                                    {
                                        for(register int bc = 0; bc <= 1; ++bc)
                                        {
                                            if((ba + bb + j & 1) != bc) continue;
                                            dp[i + 1][ca + ba][cb + bb][cc + bc][ba + bb + j >> 1] = min
                                            (
                                                dp[i + 1][ca + ba][cb + bb][cc + bc][ba + bb + j >> 1],
                                                dp[i][ca][cb][cc][j] + (bc << i)
                                            );
                                        }
                                    }
                                }
                            }
                                
                        }
                    }
                }
            }
            if(dp[len][cnta][cntb][cntc][0] < INF) cout << dp[len][cnta][cntb][cntc][0] << "
    ";
            else cout << "-1
    "; 
        }
        return 0;
    } 
    参考程序
  • 相关阅读:
    2019年春第八周作业
    2019 第七周作业
    2019 第六周作业
    2019 第五周作业
    2019 第四周作业
    2019 第三周作业
    2019 第二周作业
    2019第一周编程总结2
    2019第一周编程总结1
    秋季学期学习总结
  • 原文地址:https://www.cnblogs.com/kcn999/p/11272676.html
Copyright © 2011-2022 走看看