巧妙的运用进制, 可以解决很多问题!
怎么快速的转换进制:
//了解
#include<bits/stdc++.h>
using namespace std;
int main() {
char s2[100];
itoa(101, s2, 2);
cout << s2 << endl;
return 0;
}
itoa (要转换的数,转换放在那个数组(char), 转换成几进制);
二进制的运用:
1.二进制 + DP = 状态压缩DP;
eg: 91. 最短Hamilton路径 - AcWing题库
/*//
Problem:91.最短Hamilton路径
Contest: 基础算法
URL: https://www.acwing.com/problem/content/1000/
/*/
#include <bits/stdc++.h>
#define ll long long int
#define ull unsigned long long int
using namespace std;
const int inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
const int N = 20;
const int M = 1 << N;
int n;
int mp[N][N];
int f[M][N];
void init() {
memset(f, inf, sizeof f);
f[1][0] = 0;
}
int solve() {
init();
for (int i = 0; i < 1 << n; i ++) {
for (int j = 0; j < n; j ++) {
if (i >> j & 1) {
for (int k = 0; k < n; k ++) {
if (((i - (1 << j)) >> k) & 1) {
f[i][j] = min(f[i - (1 << j)][k] + mp[k][j], f[i][j]);
}
}
}
}
}
return f[(1 << n) - 1][n - 1];
}
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
for (int i = 0; i < n; i ++) {
for (int j = 0; j < n; j ++) {
cin >> mp[i][j];
}
}
cout << solve() << endl;
return 0;
}
2.二进制 + 乘法 = (一定程度上)大数乘法
/*//
Problem:90. 64位整数乘法
Contest: 基本算法
URL: https://www.acwing.com/problem/content/description/92/
/*/
#include <bits/stdc++.h>
#define ll long long int
#define ull unsigned long long int
using namespace std;
const int inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
void solve(ll a, ll b, ll p) {
ll res = 0;
while (b) {
if (b & 1) {
res = (res + a) % p;
}
a = (2 * a) % p;
b /= 2;
}
cout << res << endl;
}
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
ll a, b, p;
cin >> a >> b >> p;
solve(a, b, p);
return 0;
}
3.二进制 + 搜索 = 经典多钥匙开门搜索问题(每一位对应一个数、一把钥匙)/ 或者情况选择问题:
/*//
Problem: 998. 起床困难综合症
Contest: 基础算法
URL: https://www.acwing.com/problem/content/1000/
/*/
#include <bits/stdc++.h>
#define ll long long int
#define ull unsigned long long int
using namespace std;
const int inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n, m;
struct door {
string op;
int w;
} dor[2 * maxn];
int OP(int a, int b) {
int res = a;
for (int i = 1; i <= n; i ++) {
if (dor[i].op[0] == 'A') {
res &= dor[i].w >> b & 1;
}
if (dor[i].op[0] == 'O') {
res |= dor[i].w >> b & 1;
}
if (dor[i].op[0] == 'X') {
res ^= dor[i].w >> b & 1;
}
}
return res;
}
int solve() {
int ans = 0;
for (int i = 32; i >= 0; i --) {
if (m >> i) {
int one = OP(1, i);
int zero = OP(0, i);
if (zero >= one) {
ans |= zero << i;
} else {
ans |= one << i;
}
} else {
ans |= OP(0, i) << i;
}
}
return ans;
}
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
cin >> dor[i].op >> dor[i].w;
}
cout << solve() << endl;
return 0;
}
/*//
Problem: 92. 递归实现指数型枚举
Contest: 递归与递推
URL: https://www.acwing.com/problem/content/94/
/*/
#include <bits/stdc++.h>
#define ll long long int
#define ull unsigned long long int
using namespace std;
const int inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
// 注意这里面选 0 个时要输出空格
int n;
void solve(int x, int state) {
if (x == n) {
for (int i = 0; i < n; i ++) {
if (state >> i & 1) {
cout << i + 1 << " ";
}
}
cout << endl;
return;
}
solve(x + 1, state | (1<<x));
solve(x + 1, state);
}
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
solve(0, 0);
return 0;
}
/*//
Problem: 93. 递归实现组合型枚举
Contest: 递归与递推
URL: https://www.acwing.com/problem/content/95/
/*/
#include <bits/stdc++.h>
#define ll long long int
#define ull unsigned long long int
using namespace std;
const int inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n, m;
struct node {
int state1;
int cnt;
};
// bool cmp(node x1, node x2) {
// return x1.state1 > x2.state1;
// }
vector<node > ans;
void solve(int x, node state, int flag) {
if (flag) {
state.cnt ++;
state.state1 |= (1 << (x-1));
}
if (x == n) {
if (state.cnt == m) {
ans.push_back(state);
}
return ;
}
solve(x + 1, state, 1);
solve(x + 1, state, 0);
}
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m;
node state;
state.cnt = 0;
state.state1 = 0;
solve(0, state, 0);
// sort(ans.begin(), ans.end(), cmp);
reverse(ans.begin(), ans.end());
for(int i = 0; i < ans.size(); i ++) {
for(int j = 0; j < n; j ++) {
if(ans[i].state1 >> j & 1) {
cout << j + 1 << " ";
}
}
cout << endl;
}
return 0;
}
总而言之二进制非常好用!