洛谷P1100 位运算+进制转换解释
AC代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
unsigned int a;
cin>>a;
cout<<(a>>16)+(a<<16)<<endl;
return 0;
}
你没有看错,就是这么简单,就是这么酸爽,上个月写的70行代码记忆犹新…
先聊聊二进制吧
总所周知,计算机的记录方式是二进制记录,即计算机的世界是0和1的世界。但我们现实生活却属于十进制的世界,那么如何将十进制转化为二进制呢?
实现代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int s[100];
int main()
{
int i=-1;
unsigned int n;
cin>>n;
while(n)
{
s[++i]=n%2;
n=n-s[i];
if(n/2==0)
break;
else n=n/2;
}
for(int j=i;j>=0;j--)
cout<<s[j]<<' ';
cout<<endl;
return 0;
}
如果单看这段代码实际上是比较抽象的,但当你了解如何将二进制转化为十进制就懂了!
比如说:
5=101=((1*2)+0)*2+1
那么在十进制转二进制中:
过程一:
5%2=1 这个1 就相当于上面式子的最后一个1。
5-1=4
4/2=2
过程二:
2%2=0 这个0就相当于括号内的那个0。
2-0=2
2/2=1
过程三:
1%2=1 这个1相当于开始的那个1。
1/2=0 结束循环。
所以5的二进制是101
二进值转十进值代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{
int sum=0;
char s[100];
gets(s);
int len=strlen(s);
for(int i=0;i<len;i++)
{
sum=sum*2+s[i]-'0';
}
cout<<sum<<endl;
return 0;
}
在聊完二进制后再聊聊 unsigned
以前总是可以看到一些大佬的代码里有 unsigned int ans 这个定义,一开始我还是不太了解为什么要定义一个unsigned,直接int不好吗,但学了位运算后明白的彻底。
首先必须知道 int的有效位数是32位,long long的位数是64位。
32位的意义是用二进制存储可以用32个1,即 1111…111 但是int定义的最大位应该是31位,因为最前面的那一位是符号判断位,如果是0,就是正数,如果是1则表示负数。
而如果用unsigned int 则最大位可以达到32位,因为最前面的那一位不用用来当成符号判断位了。
知道了这些后,就应该要学会位运算了
位运算的功能强大到可怕,我也是一知半解,但我发现一篇很好的文章,就直接引用了:
https://blog.csdn.net/deaidai/article/details/78167367
最后再聊回题目本身
给出一个小于32位的正整数。这个数可以用一个3232位的二进制数表示(不足3232位用00补足)。我们称这个二进制数的前1616位为“高位”,后1616位为“低位”。将它的高低位交换,我们可以得到一个新的数。试问这个新的数是多少(用十进制表示)。
例如,数13145201314520用二进制表示为0000 0000 0001 0100 0000 1110 1101
100000000000000101000000111011011000(添加了1111个前导00补足为3232位),其中前1616位为高位,即0000
0000 0001 01000000000000010100;后1616位为低位,即0000 1110 1101
10000000111011011000。将它的高低位进行交换,我们得到了一个新的二进制数0000 1110 1101 1000 0000
0000 0001
010000001110110110000000000000010100。它即是十进制的249036820249036820。
这题有坑,如果你是先把十进制转化为二进制,再调换位置,再将二进制转化为十进制的,那么你已经输了一半了。
我再次强调,在计算机里,存储是二进制存储,那么即使你输入的是一个十进值的数,它在计算机里表达的还是二进制,所以你只需要通过位运算模拟题目就行。所以本题AC代码简短到令人害怕。