CSP-S 2019初赛知识点总结之位运算和二分

位运算

这里

位运算主要包括按位与(&)、按位或(|)、按位异或(^)、取反(~ )、左移(<<)、右移(>>)这几种,其中除了取反(~)以外,其他的都是二目运算符,即要求运算符左右两侧均有一个运算量。

进制转换

B:二进制数
O:八进制数
D:十进制数
H:十六进制数

(1)二进制转十进制

按权展开求和

(2)十进制转二进制

整数:除以2取余,逆序输出

小数:乘以2取整,顺序输出

其他进制同理(感性理解即可)

原码、补码和反码

这个博客讲的挺好的:https://www.cnblogs.com/author/p/8954127.html

原码

是计算机中一种对数字的二进制定点表示方法。原码表示法在数值前面前面有一位符号位(即最高位为符号位),正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。

原码是有符号数的最简单的编码方式,便于输入输出,但作为代码加减运算时较为复杂,故计算机一般不采用这种编码方式存储符号数。

反码

正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外

由于-0这个问题的存在,会使得计算机需要增加额外的物理硬件配合运算,所以在计算机发展的早期就已经抛弃了使用反码储存数据。

补码

正数和+0的补码是其原码,负数则先计算其反码,然后反码加上1,得到补码。

补码换算为原码的过程中,如果补码是正数或者+0的补码,则其原码就是补码本身;如果补码是负数或者-0的补码,则其原码的计算方法是,先将补码减掉1,得到反码,再将反码取反,得到原码。

按位与(&)

参加运算的两个数,换算为二进制(0、1)后,进行与运算。只有当相应位上的数都是1时,该位才取1,否则该位为0。

按位或(|)

参加运算的两个数,换算为二进制(0、1)后,进行或运算。只要相应位上存在1,那么该位就取1,均不为1,即为0。

按位异或(^)

参加运算的两个数,换算为二进制(0、1)后,进行异或运算。只有当相应位上的数字不相同时,该为才取1,若相同,即为0。

任何数与0异或,结果都是其本身。

异或还可以交换两个数

a = a ^ b;
b = b ^ a;
a = a ^ b;
取反(~)

参加运算的两个数,换算为二进制(0、1)后,进行取反运算。每个位上都取相反值,1变成0,0变成1。

左移(<<)

在二进制表示下把数字同时向左移动,低位以0填充,高位越界后舍弃

1 << n = 2 ^ n
n << 1 = 2n
右移(>>)

在二进制补码表示下把数字同时向右移动,高位以符号位填充,低位越界后舍弃(算术右移)

算术右移等于除以2向下取整

注意

c++中,两个数值执行算术运算时,以参与运算的最高数值类型为基准,与保存结果的变量类型无关,所以要用到强制转换。

快速幂
long long Pow(long long x, long long y)
{
	long long t = 1;
	while (y)
	{
		if (y & 1) t = t * x % mod;
		y /= 2;
		x = x * x % mod;
	}
	return t % mod;
}
快速乘
long long mul(long long x, long long y)
{
	long long t = 0;
	while (y)
	{
		if (y & 1) t = (t + x) % mod;
		y /= 2;
		x = (x + x) % mod;
	}
	return t % mod;
}
二进制状态压缩

指将一个长度为m的bool数组用一个m位二进制整数表示并存储的方法

操作运算
取出整数n在二进制表示下的第k位(n >> k) & 1
取出整数n在二进制表示下的第 0~k-1位n & ((1 << k) - 1)
把整数n在二进制下的第k位取反n ^ (1 << k)
对整数n在二进制下的第k位赋1n or (1 << k)
对整数n在二进制下的第k为赋0n & (~(1 << k))
运算优先级

从高到低

! (逻辑非)、~(按位取反)
/(除)、*(乘)、%(取模)
+((加)、-(减)
<<(位左移)、>>(位右移)
<(小于)、<=(小于等于)、>(大于)、>=(大于等于)
==(恒等于)、!=(不等于)
&(位与运算)
^(位异或运算)
or(位或运算)

注:∧逻辑与,∨逻辑或

成对变换

当n为偶数时, n ^ 1 = n + 1

当n为奇数时, n ^ 1 = n - 1

lowbit运算

lowbit(n) 定义为非负整数 n 在二进制表示下“最低位的1及其后面所有的0”构成的数值

lowbit(n) = n & (~n + 1) = n & (-n)

(不行,放张zyl的图片洗洗脑子)
在这里插入图片描述

指针和引用

这篇博客:https://blog.csdn.net/weixin_42878758/article/details/82865314

指针 *

指针是指向变量的地址

简单的例子分析:

int main()
{
	int a = 3;
	int *b = &a;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	*b = 10;
	cout << "&a:" << &a << endl;
	cout << "b:" << b << endl;
	cout << "a:" << a << endl;
	system("pause");
}

结果:

a:3
b:00EFFE28
&a:00EFFE28
b:00EFFE28
a:10

分析:

b是a的指针,指向a的地址。(也就是a与b相连,只要修改*b的值,a的值也跟着改动)

引用 &

引用可说把a变量换了一个名字为b即:

&b=a

简单的例子分析:

int main()
{
	int a = 3;
	int &b = a;
	int c = a;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "c:" << c << endl;
	b = 10;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "c:" << c << endl;
	cout << "&a:" << &a << endl;
	cout << "&b:" << &b << endl;
	cout << "&c:" << &c << endl;
	system("pause");
}

结果:

a:3
b:3
c:3
a:10
b:10
c:3
&a:0019FD74
&b:0019FD74
&c:0019FD5C

分析:

& 引用 :比如说,一个人有多少外号,但都是指这个人,引用也是这样。如果b的值改动了,也就代表了a的值改动了。

(核心)函数的参数

1>函数传入普通参数

void fun(int a,int b)
{
	int c = 0;
	c = a;
	a = b;
	b = c;
}
int main()
{
	int a = 1;
	int b = 2;
	cout << a << "," << b << endl;
	fun(a, b);//a,b交换
	cout << a << "," << b << endl;
	system("pause");
	return 0;
}

结果:

1,2
1,2

分析:

函数传入的是形参,不会改变main()中a,b的地址,也就是不会改变a,b的值。

2>函数传入指针参数

void fun(int *a, int *b)
{
	int c = 0;
	c = *a;
	*a = *b;
	*b = c;
}
int main()
{
	int a = 1;
	int b = 2;
	cout << a << "," << b << endl;
	fun(&a, &b);//a,b交换
	cout << a << "," << b << endl;
	system("pause");
	return 0;
}

结果:

1,2
2,1

分析:

函数的参数传入的是指针,即地址。函数中a,b的交换是地址的交换。最后main()中的a,b的值也就改变了。

3>引用传入函数参数(简单–好操作)

void fun(int &a, int &b)
{
	int c = 0;
	c = a;
	a = b;
	b = c;
}
int main()
{
	int a = 1;
	int b = 2;
	cout << a << "," << b << endl;
	fun(a, b);//a,b交换
	cout << a << "," << b << endl;
	system("pause");
	return 0;
}

结果:

1,2
2,1

分析:

本质上是把main()中的a,b变量 换了个名字,即:函数中的a,b,函数中的a,b地址与main()中的地址是一样的。如果函数中的a,b值改变的,那么main()中的a,b的值也跟着改变。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值