📜  更改位以产生特定的或值

📅  最后修改于: 2021-04-24 18:22:04             🧑  作者: Mango

给定两个正整数A和B,我们最多可以更改两个数字中的K个位,以使它们的OR等于给定的目标数T。在有多个解的情况下,请尝试使A尽可能小。

例子 :

Input : A = 175,
        B = 66,
        T = 100,
        K = 5
Output : A = 36
         B = 64
Initial bits of A = 1010 1111
Changed bits of A = 0010 0100
Initial bits of B = 0100 0010
Changed bits of B = 0100 0000
OR of changed Bits = 0110 0100
Which has decimal value equal to Target T.

Input : A = 175,
        B = 66,
        T = 100,
        K = 4
Output : Not Possible
It is not possible to get OR of
A and B as T, just by changing K bits.

我们可以通过遍历A和B的所有位并贪婪地更改它们来解决此问题,即,

  • 如果目标T的第i位为0,则将A和B的第i位设置为0(如果尚未设置)
  • 如果目标T的第i位为1,那么我们将尝试将其中一个位设置为1,然后将B的第i位仅更改为1(如果尚未更改)以最小化A。

在上述过程之后,如果更改的位大于K ,那么最多更改K个位就不可能获得A和B的OR为T。
如果更改的位小于k ,那么我们可以通过使用K的剩余值来进一步最小化A的值,为此我们将在位上循环一次,如果在任何时候,

  • 第i个A位为1,第i个B位为0,那么我们将进行2次更改并将两者翻转。
  • 第i个A和B位为1,然后再次更改1并翻转A的位。

上述解决方案的总时间复杂度将为O(最大位数)。

C++
// C++ program to change least bits to
// get desired OR value
#include 
using namespace std;
  
// Returns max of three numbers
int max(int a, int b, int c)
{
    return max(a, max(b, c));
}
  
// Returns count of bits in N
int bitCount(int N)
{
    int cnt = 0;
    while (N)
    {
        cnt++;
        N >>= 1;
    }
    return cnt;
}
  
// Returns bit at 'pos' position
bool at_position(int num, int pos)
{
    bool bit = num & (1<= 0; i--)
    {
        bool bitA = at_position(A, i);
        bool bitB = at_position(B, i);
        bool bitT = at_position(T, i);
  
        // T's bit is set, try to toggle bit
        // of B, if not already
        if (bitT)
        {
            if (!bitA && !bitB)
            {
                toggle(B, i);
                K--;
            }
        }
        else
        {
            //    if A's bit is set, flip that
            if (bitA)
            {
                toggle(A, i);
                K--;
            }
  
            //    if B's bit is set, flip that
            if (bitB)
            {
                toggle(B, i);
                K--;
            }
        }
    }
  
    //    if K is less than 0 then we can make A|B == T
    if (K < 0)
    {
        cout << "Not possible\n";
        return;
    }
  
    // Loop over bits one more time to minimise
    // A further
    for (int i = maxlen - 1; K > 0 && i >= 0; --i)
    {
        bool bitA = at_position(A, i);
        bool bitB = at_position(B, i);
        bool bitT = at_position(T, i);
  
        if (bitT)
        {
            // If both bit are set, then Unset
            // A's bit to minimise it
            if (bitA && bitB)
            {
                toggle(A, i);
                K--;
            }
        }
  
        // If A's bit is 1 and B's bit is 0,
        // toggle both
        if (bitA && !bitB && K >= 2)
        {
            toggle(A, i);
            toggle(B, i);
            K -= 2;
        }
    }
  
    //    Output changed value of A and B
    cout << A << " " << B << endl;
}
  
// Driver code
int main()
{
    int A = 175, B = 66, K = 5, T = 100;
    minChangeToReachTaregetOR(A, B, K, T);
    return 0;
}


PHP
>= 1;
    }
    return $cnt;
}
  
// Returns bit at 'pos' position
function at_position($num, $pos)
{
    $bit = $num & (1 << $pos);
    return $bit;
}
  
// Utility method to toggle
// bit at 'pos' position
function toggle(&$num, $pos)
{
    $num ^= (1 << $pos);
}
  
// method returns minimum 
// number of bit flip to 
// get T as OR value of A and B
function minChangeToReachTaregetOR($A, $B,
                                   $K, $T)
{
    $maxlen = max(bitCount($A),
                  bitCount($B),
                  bitCount($T));
  
    // Loop over maximum number 
    // of bits among A, B and T
    for ( $i = $maxlen - 1; $i >= 0; $i--)
    {
        $bitA = at_position($A, $i);
        $bitB = at_position($B, $i);
        $bitT = at_position($T, $i);
  
        // T's bit is set, try to toggle
        // bit of B, if not already
        if ($bitT)
        {
            if (!$bitA && !$bitB)
            {
                toggle($B, $i);
                $K--;
            }
        }
        else
        {
            // if A's bit is set, 
            // flip that
            if ($bitA)
            {
                toggle($A, $i);
                $K--;
            }
  
            // if B's bit is set,
            // flip that
            if ($bitB)
            {
                toggle($B, $i);
                $K--;
            }
        }
    }
  
    // if K is less than 0 then
    // we can make A|B == T
    if ($K < 0)
    {
    echo "Not possible\n";
        return;
    }
  
    // Loop over bits one more 
    // time to minimise A further
    for ($i = $maxlen - 1; 
         $K > 0 && $i >= 0; --$i)
    {
        $bitA = at_position($A, $i);
        $bitB = at_position($B, $i);
        $bitT = at_position($T, $i);
  
        if ($bitT)
        {
            // If both bit are set, then 
            // Unset A's bit to minimise it
            if ($bitA && $bitB)
            {
                toggle($A, $i);
                $K--;
            }
        }
  
        // If A's bit is 1 and B's 
        // bit is 0, toggle both
        if ($bitA && !$bitB && $K >= 2)
        {
            toggle($A, $i);
            toggle($B, $i);
            $K -= 2;
        }
    }
  
    // Output changed value
    // of A and B
    echo $A , " " , $B , "\n";
}
  
// Driver Code
$A = 175;
$B = 66;
$K = 5;
$T = 100;
minChangeToReachTaregetOR($A, $B, $K, $T);
  
// This code is contributed by ajit
?>


输出 :

36 64