快速幂
#include <iostream>
using namespace std;
int main()
{
int a, b, p;
cin >> a >> b >> p;
int res = 1 % p; //模p是防止当p == 1 && b == 0时输出1, 正确答案应为0
while(b){
if(b&1) res = res * 1ll * a % p; //1ll可强制转化为long long类型
a = a * 1ll * a % p;
b >>= 1;
}
cout << res << endl;
return 0;
}
/*
该问题求a^b mod p
数据范围: 0≤a,b≤10^9, 1≤p≤10^9
时间复杂度: O(log b)
res用来表示乘积;
快速幂:
3^7 = 3^1 + 3^2 + 3^4;
b每次右移1位, 为1时, res乘a
*/
#include <iostream>
using namespace std;
typedef unsigned long long ULL;
int main()
{
ULL a, b, p;
cin >> a >> b >> p;
ULL res = 0;
while(b){
if(b&1) res = (res + a) % p;
a = 2 * a % p;
b >>= 1;
}
cout << res << endl;
return 0;
}
/*
10^18大概等于2^64, 因此要用unsigned long long
相当于b个a相加
a * b = a + a + a + a + a + a + ...
a * 1 = a
a * 2 = 2a
a * 4 = 4a
...
a *(2^k) =(2^k)a
*/
例题1:最短Hamilton路径(又名:旅行商问题)
位运算的精髓:按位枚举,可将O(n)转化为O(log n)
/*
Hamilton 路径的定义是从 0 到 n−1 不重不漏地经过每个点恰好一次
假设有4个点:0, 1, 2, 3
0->1->2->3 18
0->2->1->3 20
由此可知, 一个Hamilton路径与中间点无关, 且最短Hamilton路径可以由以下两点表示状态:
1.哪些点被用过(可以用二进制数表示, 1表示用过, 0表示没用过)
2.目前停在哪个点上
f[state][j] = f[state_k][k] + weight[k][j](由k转移到j), state_k表示state去掉j之后的集合, 且state_k要包含k
如果用到了点0 1 4, 则state = 10011
*/
#include <iostream>
#include <cstring>
using namespace std;
const int N = 20, M = 1 << 20;
int n, weight[N][N];
int f[M][N];
int main()
{
cin >> n;
for(int i = 0; i < n; i ++ )
for(int j = 0; j < n; j ++ )
cin >> weight[i][j];
memset(f, 0x3f, sizeof f); //因为要求最小值, 所以将f设置最大
f[1][0] = 0;
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][j], f[i - (1 << j)][k] + weight[k][j]);
cout << f[(1 << n) - 1][n - 1] << endl;
return 0;
}