刷题心得之位运算技巧 gcd 和 lcm

位运算技巧

遍历 n 的所有子集, 不包括空集

#include <cstdio>
#include <iostream>

using namespace std;

// 打印一个数的二进制, 方便理解
void Print(int n)
{
	for (int i = 31; i >= 0; i--)
	{
		cout << ((n >> i) & 1);
	}
	cout << endl;
}

// 从大到小,枚举 n 的所有非空子集
void test2(int n)
{
	for (int sub = n; sub; sub = (sub - 1) & n)
	{
		printf("%4d---", sub);
		Print(sub);
	}
}

int main()
{
	cout << "枚举 n 的所有子集,不包括空集" << endl;
	test2(77);
	
	return 0;
}

遍历 n 的所有子集, 包括空集

#include <cstdio>
#include <iostream>

using namespace std;

// 打印一个数的二进制, 方便理解
void Print(int n)
{
	for (int i = 31; i >= 0; i--)
	{
		cout << ((n >> i) & 1);
	}
	cout << endl;
}

// 从大到小枚举 n 的所有子集 【从 n 枚举到空集】
void test1(int n)
{
	int sub = n;
	do
	{
		printf("%4d---", sub);
		Print(sub);
		sub = (sub - 1) & n;
	} while (sub != n);
}

int main()
{
	cout << "枚举 n 的所有子集,包括空集" << endl;
	test1(77);
	
	return 0;
}

提取出 n 二进制中第一次出现的1

#include <cstdio>
#include <iostream>

using namespace std;

// 打印一个数的二进制, 方便理解
void Print(int n)
{
	for (int i = 31; i >= 0; i--)
	{
		cout << ((n >> i) & 1);
	}
	cout << endl;
}

// 提取出 n 二进制中第一次出现的1
void test4(int n)
{
	// 二进制中 n 第一次出现1的位置
	int tem = n & (-n);
	printf("%4d---", tem);
	Print(tem);
}

int main()
{
	cout << "提取出 n 第一次出现1的位置" << endl;
	printf("%4d---", 40);
	Print(40);
	test4(40);
	
	return 0;
}

消除 n 二进制中第一次出现的1

#include <cstdio>
#include <iostream>

using namespace std;

// 打印一个数的二进制, 方便理解
void Print(int n)
{
	for (int i = 31; i >= 0; i--)
	{
		cout << ((n >> i) & 1);
	}
	cout << endl;
}

// 消除 n 二进制中第一次出现的1
void test5(int n)
{
	// 消除
	int tem = n & (n - 1);
	printf("%4d---", tem);
	Print(tem);
}

int main()
{
	cout << "消除 n 二进制中第一个1" << endl;
	printf("%4d---", 50);
	Print(50);
	test5(50);
	
	return 0;
}

判断 n 是否是 2 的幂次方

#include <cstdio>
#include <iostream>

using namespace std;

// 打印一个数的二进制, 方便理解
void Print(int n)
{
	for (int i = 31; i >= 0; i--)
	{
		cout << ((n >> i) & 1);
	}
	cout << endl;
}

// 判断 n 是否是2的幂次方
void test6(int n)
{
	// 特判 0 
	if (n == 0)
	{
		printf("%4d--- NO  ", n);
		Print(n);
	}
	// 2的幂次方, 二进制中有且只有一位是1
	else
	{
		if ((n & (n - 1)) == 0)
		{
			printf("%4d---YES  ", n);
			Print(n);
		}
		else
		{
			printf("%4d--- NO  ", n);
			Print(n);
		}
	}
}

int main()
{
	for (int i = 0; i < 30; i++)
	{
		test6(i);
	}
	
	return 0;
}

gcd [最大公约数]

#include <cstdio>
#include <iostream>

using namespace std;

// 输出 m 和 n 的最大公约数
// 辗转相除法
int gcd(int m, int n)
{
	// 默认认为 m >= n
	if (m < n )  return gcd(n, m);
	if (n == 0)  return m;
	return gcd(n, m % n);
}

int main()
{
	int m = 13, n = 65;
	int res = gcd(m, n);
	printf("%d 和 %d 的最大公约数是: %d", m, n, res);
	
	return 0;
}

lcm [最小公倍数]

#include <cstdio>
#include <iostream>

using namespace std;

// 输出 m 和 n 的最小公倍数
int lcm(int m, int n)
{
	return (m * n) / gcd(m, n);
}

int main()
{
	int m = 13, n = 65;
	int res = lcm(m, n);
	printf("%d 和 %d 的最小公倍数是: %d\n", m, n, res);
	
	return 0;
}


黄梅时节家家雨,青草池塘处处蛙。
有约不来过夜半,闲敲棋子落灯花。
— — <约客> 赵师秀 [宋]

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨 子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值