好了今年最后一天,写一个博客好了.
先说题:
首先我们打开计算器调到程序员来模拟一下样例:
题意就是对于这个数n如何加上一个新数后使得二进制下的新数1的数量小于等于k
考虑贪心,设答案是ans,为了让ans最小当然要使得新数最小.每次必须要往上加,那答案应该是把第k个1和之后的1都弄掉,换成这样子:
这个贪心应该容易想到吧.如果之前没有位置,例如
且k=5的话为了把最后一个1弄掉不得不换成:
这个过程有点难写代码实现,我第一次写了个类似模拟一样的东西:
循环每一位,由于每次循环后都除以2了,所以只需要判断最低位是否为1就可以了,如果为1就加上1<<i往前推,总会有机会把总的1的个数变少的(check函数是返回n二进制下的1的个数的函数).
后来我就想到,这个每次找到最后一个1并加一下的操作好像在哪见过啊,lowbit不就是这样的操作么?这样只需要用lowbit就可以快速水过本题了:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using namespace std; int sum; int n,k,ans; inline int lowbit(int kk){ return kk&(-kk); } inline int check(int kk){ sum=0; while(kk){ sum+=kk&1; kk>>=1; } return sum; } int main(){ cin>>n>>k; while(check(n)>k){ ans+=lowbit(n); n+=lowbit(n); } cout<<ans; return 0; }
复杂度的话,这个过程最多进行log2(n)次,每次的check()函数也是log2(n)的,所以总复杂度是log2^2(n)
我第一篇博客就是今年的1月2号跑到机房写的,当时还啥都不会了,然后寒假在一中集训一下,去省选长见识,去海亮集训一下长见识,停课一个月长见识练能力,NOIP拿到省一等奖都是非常刻骨铭心的体验,感觉一年来飞速的在成长了.具体表现在80篇博客与460道刷题量上.其实拿到省一并且不退役在刚开始学的时候是非常不敢想象的,一点一点走过来之后竟然真的可以,就很开心.
是不是又要谈学习目标或者说理想了呢?我刚开始学的时候不过是兴趣,后来因为可以天天上qq而坚持了下来,现在应该是为了有一个途径可以考上那个学校了而已吧.
嗯我会努力去南京大学的,至少可以离大大近一点.
过几天又要停课了,这次是为了准备省选.好像要停三个月,但是我丝毫不虚.
大大,我喜欢你啊.