本人一些C++容易用混的运算符

C++ 运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。

(1) 逻辑运算符

运算符描述实例
&&称为逻辑与运算符。如果两个操作数都为非零,则条件为真(A&&B)为假
||称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真(A||B)为真
称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假!(A&&B)为真
#include <iostream>
using namespace std;

int main()
{
	int a = 5;
	int b = 20;
	int c;
	if(a&&b)
		cout << "Line 1 - 条件为真" << endl;
	if(a||b)
		cout << "Line 2 - 条件为真" << endl;
	a = 0;
	b = 10;
	if(a&&b)
		cout << "Line 3 - 条件为真" << endl;
	else
		cout << "Line 4 - 条件不为真" << endl;
	if(!(a&&b))
		cout << "Line 5 - 条件为真" << endl;
	return 0;
}

开灯问题(涉及逻辑运算符问题)
有 n 盏灯,编号为 1~n。第 1 个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依次类推。一共有k个人,问最后有那些灯开着?输入 n 和 k,输出开着的灯的编号。k<=n<=1000。

	样例输入:7 3
	样例输出:1 5 6 7

思路:用数组存一下状态。

#include <iostream>
#include <array>
using namespace std;
int main()
{
	//有 n 盏灯,k 个人
	int n,k;
	cin >> n >> k;
	array<bool,1010> deng {false};
	for(int i=1;i<=k;i++)
	{
		for(int q=1;q<=n;q++)
		{
			if(q%i==0){
				deng[q] = !deng[q]; //这里的!就是逻辑非,即如果是1则返回0 
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(deng[i]==true)
			cout << i << endl;
	}
}

(2)位运算符:
位运算符作用于位,并逐位执行操作。&、| 和 ^ 的真值表如下所示:

pqp&qp | qp ^ q
00000
01011
11110
10011

假设如果 A = 60 ,且 B = 13 ,现在以二进制格式表示,他们如下所示:
A = 0011 1100
B = 0000 1101


A & B = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
~A = 1100 0011
下表显示了C++ 支持的位运算符。假设变量 A 值为60,变量 B 的值为13,则:

运算符描述实例
&如果同时存在于两个操作数中,二进制AND运算符复制一位到结果中。(A&B)将得到12,即为0000 1100
|如果存在于任一操作数中,二进制OR运算符复制一位到结果中。(A|B)将得到61,即为0011 1101
^如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中(A^B)将得到49,为0011 0001
~二进制补码运算符是一元运算符,具有”翻转“位效果,即0变成1,1变成0。(~A)将得到-61,即为1100 0011,一个有符号二进制数的补码形式
<<二进制左移操作符。左操作数的值向左移动右操作数指定的位数A<<2 将得到240,即为1111 0000
>>二进制右移运算符。左操作数的值向右移动右操作数指定的位数A>>2 将得到15,即为0000 1111
#include <iostream>
using namespace std;

int main()
{
	unsigned int a = 60;
	unsigned int b = 13;
	int c = 0;
	
	c = a & b;
	cout << "Line 1 - c 的值是 " << c << endl;
	
	c = a | b;
	cout << "Line 2 - c 的值是 " << c << endl;
	
	c = a ^ b;
	cout << "Line 3 - c 的值是 " << c << endl;

	c = ~a;
	cout << "Line 4 - c 的值是 " << c << endl;

	c = a << 2;
	cout << "Line 5 - c 的值是 " << c << endl;

	c = a >> 2;
	cout << "Line 6 - c 的值是 " << c << endl;
	return 0; 
}

说到位运算,首先要知道数字在计算机中的存储方式,这里只说整数。

正整数 在计算机中是以原码的形式存储的。也可以说是补码 或者 反码,因为 正整数的 原码 , 反码 和补码 是一样的。
负整数 在计算机中 是以补码的形式存储的。负数的补码等于负数的反码+1。

原码是什么?
正数的原码就是转化为二进制的这个数,负数的原码就是负数的绝对值转化为二进制,然后在最高位补1。

举例说明:

int类型的 3 的原码
00000000 00000000 00000000 00000011

int类型的 -3 的原码
10000000 00000000 00000000 00000011

反码是什么?
正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反

举例说明:

int类型的 3 的反码是
00000000 00000000 00000000 00000011

int类型的 -3 的反码是
11111111 11111111 11111111 11111100

补码是什么?
正数的补码与原码相同,负数的补码为反码最低位+1后的值

举例说明:

int类型的 3 的补码是:
00000000 00000000 00000000 00000011

int类型的 -3 的补码是:
11111111 11111111 1111111 11111101

这就解释了,为什么 int a = 1; ~a+1等于-1。对正数取反,则是那个负数的反码再+1,就是补码,又因为负数是补码存储,所以输出是负数值。对负数取反,是正数的小一个的数,由上面可知,再加一就是正数

<< 和 >> 运算符

<<运算符
1 左移1位 10 左移2位 100  (相当于2^n)
n 右移x位 = n/2^x 

注意是算术右移,如果是正数最高位补零,如果是负数最高位补1

a^b(快速幂)
求 a 的 b 次方对 p 取模的值。

输入格式
三个整数a,b,p,在同一行用空格隔开。
输出格式
输出一个整数,表示a^b mod p 的值
数据范围
1<=a,b,p<=10^9

输入样例:
3 2 7
输出样例:
2

思路:求a^b%p 如果暴力乘的话,数据范围太大,肯定会爆掉,如果将b用2进制表示
2^0 =
2^1 =
2^2 =
2^4 =
再进行判断如果,b的该二进制位是1的话对最终结果乘上a^b
复杂度是log(n)级别

#include <iostream>
using namespace std;
int main()
{
	int a,b,p;
	cin >> a >> b >> p;
	long long res = 1%p;
	while(b)
	{
		if(b&1)
			res = res*1ll*a%p; //目的是把 res * 1ll * a的乘积变成long long类型
		a = a *1ll* a%p; //同上
		b>>=1;
	}
	cout << res << endl;
}

64位整数乘法
求 a 乘 b 对 p 取模的值

输入格式
第一行输入整数a,第二行输入整数b,第三行输入整数p。
输出格式
输出一个整数,表示a*b mod p的值。
数据范围
1<=a,b,p<=10^18

输入样例
3
4
5
输出样例
2
思路:仍然是整数溢出问题,如果直接ab就会整数溢出
所以将问题转化为:
a+a+a+…+a
a = a
a = a
2
a = a4
a = a
8

再根据b的位运算

#include <iostream>
using namespace std;
int main()
{
	unsigned long long a,b,p;
	cin >> a >> b >> p;
	unsigned long long res = 0;
	while(b)
	{
		if(b&1) res = (res + a)%p;
		a = (a + a)%p;
		b>>=1;
	}
	cout << res << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值