位运算 gcd 和 lcm
- 位运算技巧
- 遍历 n 的所有子集, 不包括空集
- 遍历 n 的所有子集, 包括空集
- 提取出 n 二进制中第一次出现的1
- 消除 n 二进制中第一次出现的1
- 判断 n 是否是 2 的幂次方
- 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;
}
黄梅时节家家雨,青草池塘处处蛙。
有约不来过夜半,闲敲棋子落灯花。
— — <约客> 赵师秀 [宋]