5.10 最大异或和(Tire树+前缀异或和)
请在所有长度不超过 M 的连续子数组中,找出子数组异或和的最大值。
进行前缀异或和处理后,只需在前缀和数组中寻找两个数异或和最大即可
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010 * 31;
int n, m, s[N];
int son[N][2], cnt[N], idx;
// v为1表示加入x,v为-1表示删除x
void insert(int x, int v)
{
int p = 0;
for (int i = 30; i >= 0; --i )
{
int u = x >> i & 1;
if(!son[p][u]) son[p][u] = ++ idx;
p = son[p][u];
cnt[p] += v;
}
}
int query(int x)
{
int res = 0, p = 0;
for (int i = 30; i >= 0; -- i )
{
int u = x >> i & 1;
if(cnt[son[p][!u]])
{
p = son[p][!u];
res = res << 1 | 1;
}
else {
p = son[p][u];
res <<= 1;
}
}
return res;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
{
int x;
scanf("%d", &x);
s[i] = s[i - 1] ^ x;
}
insert(s[0], 1); // 首先要把s[0]插入
int res = 0;
for (int i = 1; i <= n; ++i)
{
if( i > m) insert(s[i - 1 - m], -1);
res = max(res, query(s[i]));
insert(s[i], 1);
}
cout << res << endl;
return 0;
}
5.11最大的和(双指针)
在不选中选择一个里面数最大的区间,采用双指针
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
typedef long long ll;
int n, k;
int a[N], b[N];
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i ++ ) cin >> a[i];
ll sum = 0;
for (int i = 0; i < n; i ++ )
{
cin >> b[i];
if(b[i]) sum += a[i];
}
ll s = 0, res = 0; // s表示当前区间值,res表示答案
for (int i = 0; i < n; ++i)
{
if(!b[i]) s += a[i]; // 加入
if(i >= k && !b[i - k]) s -= a[i - k]; // 超过k区间删除前面
res = max(res, s);
}
cout << res + sum << endl;
return 0;
}
5.12小凯的疑惑(数论)
结论:
如果 a,b均是正整数且互质,那么由 ax+by,x≥0,y≥0不能凑出的最大数是 ab−a−b
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
cout << a * b - a - b << endl;
return 0;
}
5.13不同路径数(DFS)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
int n, m, k;
char g[10][10];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
map<string, int>mp;
void dfs(int x, int y, int u, string now)
{
if(u == k)
{
mp[now] = 1;
//cout << now << endl;
return ;
}
for (int i = 0; i < 4; ++i)
{
int a = x + dx[i], b = y + dy[i];
if(a >= 1 && a <= n && b >= 1 && b <= m)
dfs(a, b, u + 1, now + g[a][b]);
}
}
int main()
{
cin >> n >> m >> k;
k++;
getchar();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &g[i][j]);
string p = "";
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
{
dfs(i, j, 0, p);
}
cout << mp.size() << endl;
return 0;
}