memset只能赋值出“每8位都相同”的int
0x7F7F7F7F是memset能初始化出的最大数组,但需要将一个数组中的数组初始化为正无穷时,为了避免加法运算上溢或者繁琐判断,一般用0x3F3F3F3F
1
<
<
n
=
2
n
1<
“整数/2”在c++实现为“除以2向零取整”,比如(-3)/2=-1
a b m o d p a^b\mod p abmodp
0
≤
a
,
b
≤
1
0
9
0≤a,b≤10^9
0≤a,b≤109
1
≤
p
≤
1
0
9
1≤p≤10^9
1≤p≤109
b = c k − 1 ∗ 2 k − 1 + c k − 2 ∗ 2 k − 2 + . . . + c 0 ∗ 2 0 b=c_{k-1}*2^{k-1}+c_{k-2}*2^{k-2}+...+c_0*2^0 b=ck−1∗2k−1+ck−2∗2k−2+...+c0∗20
a b = a c k − 1 ∗ 2 k − 1 ∗ a c k − 2 ∗ 2 k − 2 ∗ . . . ∗ a c 0 ∗ 2 0 a^b=a^{c_{k-1}*2^{k-1}}*a^{c_{k-2}*2^{k-2}}*...*a^{c_0*2^0} ab=ack−1∗2k−1∗ack−2∗2k−2∗...∗ac0∗20
且 a 2 i = a 2 i − 1 ∗ 2 = ( a 2 i − 1 ) 2 a^{2^i}=a^{2^{i-1}*2}=(a^{2^{i-1}})^2 a2i=a2i−1∗2=(a2i−1)2因此遍历b的每一位,如果当前这位是1,说明要乘上这个系数,而这个系数是随着遍历b的每一位,每次变成自己的平方
#include
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
using namespace std;
typedef long long ll;
int qmi(int a, int b, int p) {
int ans = 1 % p;
while (b) {
if (b & 1) ans = (ll)ans * a % p;
a = (ll)a * a % p;
b >>= 1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int a, b, p;
cin >> a >> b >> p;
cout << qmi(a, b, p);
}
ll ans = 1 % p
,初始化ans也要取模,否则可能b为0且p为1时,答案错误1 ≤ a , b , p ≤ 1 0 18 1≤a,b,p≤10^{18} 1≤a,b,p≤1018
将b化为二进制表示后, a ∗ b = c k − 1 ∗ a ∗ 2 k − 1 + c k − 2 ∗ a ∗ 2 k − 2 + . . . + c 0 ∗ a ∗ 2 0 a*b=c_{k-1}*a*2^{k-1}+c_{k-2}*a*2^{k-2}+...+c_0*a*2^0 a∗b=ck−1∗a∗2k−1+ck−2∗a∗2k−2+...+c0∗a∗20
又因为 a ∗ 2 i = ( a ∗ 2 i − 1 ) ∗ 2 a*2^i=(a*2^{i-1})*2 a∗2i=(a∗2i−1)∗2
发现运算过程中每一步的结果都不超过 2 ∗ 1 0 18 2*10^{18} 2∗1018,仍然在64位整数longlong的表示范围内
#include
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
using namespace std;
typedef long long ll;
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
ll a, b, p;
cin >> a >> b >> p;
ll ans = 0;
while (b) {
if (b & 1) ans = (ans + a) % p;
a = a * 2 % p;
b >>= 1;
}
cout << ans;
}
n xor (1 << k)
(结论:1、异或0不会产生变化;2、异或1会取反)n | (1 << k)
n & (~(1 << k))
(注意如何由1表示0,取反)n & ((1 << k) - 1)
(让前面的位都是0,因此&0,让后面的位原先是1的为1,原先是0的为0,因此&1)ans += (res0 << bit)
(不需要分类讨论为res0是0还是1)题意:
思路:
#include
#include
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
using namespace std;
typedef long long ll;
const int N = 20, M = 1 << 20;
int n;
int w[N][N];
int dp[M][N];
int main() {
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 >> w[i][j];
memset(dp, 0x3f, sizeof dp);
dp[1][0] = 0;
for (int i = 1; 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) {
dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + w[k][j]);
}
}
}
}
}
cout << dp[(1 << n) - 1][n - 1];
}
题意 :
思路 :
#include
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
using namespace std;
typedef long long ll;
typedef pair<string, int> psi;
const int N = 1e5 + 10;
int n, m;
psi a[N];
int calc(int bit, int now) {
for (int i = 1; i <= n; ++ i) {
string op = a[i].first;
int x = (a[i].second >> bit & 1);
if (op == "AND") now &= x;
else if (op == "OR") now |= x;
else now ^= x;
}
return now;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; ++ i) cin >> a[i].first >> a[i].second;
int ans = 0, val = 0;
for (int bit = 29; bit >= 0; -- bit) {
int res0 = calc(bit, 0);
int res1 = calc(bit, 1);
if (val + (1 << bit) <= m && res1 > res0) {
val += (1 << bit);
ans += (res1 << bit);
} else {
ans += (res0 << bit);
}
}
cout << ans;
}
lowbit(n)
定义为 非负整数n(即
n
>
0
n>0
n>0) 在二进制表示下“最低位的1及后边所有的0”所构成的数值
结论:lowbit(n) = n & (~n + 1) = n & (-n)
推导:
设n>0,n的第k位为1,第0~k-1为都是0
对n取反加一后,n的第k+1位到最高位恰好与原来相反,第0~k-1位仍然为0;即仅有第k位为1,其余位都是0;然后用原先的n & 取反加一后的n
在补码表示下,~n = -1 - n
找出整数二进制表示下所有是1的位(所花费时间与1的个数同级)(lowbit配合Hash):不断把n赋值位n - lowbit(n)
,直至n = 0 :
#include
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
using namespace std;
typedef long long ll;
int H[37];
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
for (int i = 0; i < 36; ++ i) H[(1ll << i) % 37] = i;
int n;
while (cin >> n) {
while (n > 0) {
cout << H[(n & -n) % 37] << ' ';
n -= (n & -n);
}
cout << endl;
}
}
lowbit运算也是树状数组(0x42)中的一个基本运算