题解 P1582 【倒水】

· · 题解

这道题的本质就是将n转为二进制后找到一个比它大且1的数量<=k的二进制数,然后再用此数-n

各位大佬好像都是用二进制做的,我也是,好巧

但是二进制具体如何实现上有点区别

至于为什么是二进制,楼上楼下的各位大佬已经讲的很清楚了,我就不重复了

重点讲如何实现

首先当然要先把n化为二进制,长度为l

然后去找,在前k个一中的最后一个为0的位置

如果不存在,则直接用2^(l+1)-n(前面无论怎么将1改0都没用,必须多加一位,才能使1的数量<=k

如果找到了,那就把这位变成1,后面全改为0,再拿此数去-n

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll x,n,k,a[111],l=-1,s;
ll pw(int b,int c) //建议手写pow
{
    ll sum=1;
    for(int i=1;i<=c;i++)
    {
        sum*=b;
    }
    return sum;
}
ll check()
{
    ll zz=-100;
    for(int i=l,j=1;j<=k;i--)//找位置
    {
        if(!a[i]) 
        {
            zz=i;
            //return zz;
        }
        else j++;
    }
    if(zz==-100)
    return 0;
    else return zz;
}
int main()
{
    cin>>n>>k;
    x=n;
    while(x)//转二进制
    {
        l++;
        s+=x%2;
        a[l]=x%2;
        x/=2;
    }
   if(s<=k)//根本不用做的
   {
       cout<<"0";
       return 0;
   }
   //cout<<check();
   ll z=check();
    if(!z) //没有找到
    {
        cout<<pw(2,l+1)-n;
    }
    else //找到了
    {

        a[z]=1;
        ll sum=0;
        for(int i=z;i<=l;i++)
        {
            sum+=pw(2,i)*a[i];
        }
    //    cout<<sum<<endl;
        cout<<sum-n;
    }

}