B4060 位运算 (1、2通讲)

第三篇题解,希望大家能给蒟蒻点个赞,点个关注叭!感谢支持! 

  水个题解,这两道题题解很少,很冷门,不过确实是好题。 

 第一题 

B4060 位运算 1 - 洛谷https://www.luogu.com.cn/problem/B4060

这是道位运算水题,适合新手,

只要知道这个就行,

如果不知道,

请去别的博客理解,

代码如下:

#include<bits/stdc++.h>
using namespace std;
int a,b,k;
int main(){
	cin>>a>>b>>k;
	cout<<(a&b)<<endl; //按位与
	cout<<(a|b)<<endl; //按位或
	cout<<(a^b)<<endl; //按位异或
	cout<<(~a)<<endl;  //按位取反
	cout<<(a<<k)<<endl;//左移
	cout<<(a>>k)<<endl;//右移
	return 0;
} 

 第二题 

B4060 位运算 2https://www.luogu.com.cn/problem/B4061 - 洛谷

这道题很多入用进制转换,

没!必!要!

这是谁写的代码!还要不要命了!这么长,累死入。

#转载于https://blog.csdn.net/2401_86212225/article/details/145316694#:

#include<bits/stdc++.h> 
using namespace std;
long long a,b;
int s[2000005];
void print()
{
    cout<<fixed;
    //控制显示的精度,控制小数点后面的位数。而整数太大时也会使用科学计数法,要输出完整的整数,避免科学记数法显示。
    cout<<setprecision(0);
    cout<<a*pow(2,b)<<endl;
    cout<<floor(a/pow(2,b))<<endl;
    cout<<s[b]<<endl;
    if(s[b]==0)cout<<a<<endl;
    else cout<<a-pow(2,b)<<endl;
    if(s[b]==1)cout<<a<<endl;
    else cout<<a+pow(2,b)<<endl;
    if(s[b]==1)cout<<a-pow(2,b)<<endl;
    else cout<<a+pow(2,b)<<endl;
}
void zh(long long n,long long jzs)//转换进制
{
    long long k=-1;
    s[0]=n;        
    while(s[k+1]!=0)
    {
        k++;
        while(s[k]>=jzs)
        {
            s[k+1]++;
            s[k]-=jzs;
        }
    }
}
int main()
{
    cin>>a>>b;
    zh(a,2);
    print();
    return 0; 
}

这么长的代码,

粉丝吃不下。

知周所众:

上面的代码是用进制转换,

而前两行输出不用(进制转换),

所以我们只要,

再次利用位运算解决

题目后四行输出是这样要求的:

  • a 的二进制的第 b 位;
  • 将 a 的二进制的第 b 位设置为 0 后得到的十进制结果;
  • 将 a 的二进制的第 b 位设置为 1 后得到的十进制结果;
  • 将 a 的二进制的第 b 位取反后得到的十进制结果;

所以——————

第三行:

利用按位与(&)的特性,用一个变量x1作为二进制辅助变量,x1的初始化是1(二进制也是1),用x1左移(<<)b位。用样例做解释:a是11(二进制是1011),b是2,x1的值1左移b位后变为0100(二进制数,为了方便凑4位,左边补个0,代码里不用)。我们发现,x1里“1”的位置刚好是从右往左、从0开始的b位,而利用与(&)的特性,1011&0100等于0,右移b位后还是0。举一个更鲜明的例子:a是15(二进制是1111),b是2,所以x1等于1<<b=0100,1111&0100等于0100,右移b位后是01,也就是1,就是最终结果。

第四行:

利用按位与(&)的特性,我们设置x2为反码(~)后的x1,假设x1是100,x2就是011,用样例做解释:a是11(二进制是1011),b是2,x1是100,x2就是反码(~)x1等于011,为了与1011按位与(&)同位,反码左边补1,x2等于1011。1011&1011等于1011,答案还是11(二进制1011)。

第五行:

利用按位或(|)的特性,用a直接按位或(|)x1。用样例做解释:a是11(二进制是1011),b是2,x1就是0100,1011|0100等于1111,答案是15(二进制1111)。

第六行:

直接判断a 的二进制的第 b 位是0还是1并输出对应结果。第 b 位是0则将 a 的二进制的第 b 位设置为 1;第 b 位是1则将 a 的二进制的第 b 位设置为 0。

于是——加上一、二行代码。

代码如下:

#include<bits/stdc++.h>
using namespace std;
long long a,b;
long long x1=1,x2=1;//long long是预防万一
int main(){
	cin>>a>>b;
	x1=(x1<<b);
	x2=(~x1);
	cout<<(long long)(a*pow(2,b))<<endl;//第一行,答案记得强制转换成long long,不然WA三个点
	cout<<(long long)(a/pow(2,b))<<endl;//第二行,答案记得强制转换成long long,不然WA三个点
	cout<<((a&x1)>>b)<<endl;            //第三行
	cout<<(a&x2)<<endl;                 //第四行
	cout<<(a|x1)<<endl;                 //第五行
	if(((a&x1)>>b)==1)
		cout<<(a&x2)<<endl;
	else
		cout<<(a|x1)<<endl;             //第六行
	return 0;
} 

点个赞鼓励一下叭~ ^_^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值