组合 1001 LCP Array
第一题就小难,出题的好像是浙大的大牛?
找到一个规律:a[i] = x, s[i..i+x]都想同。a[i] = a[i+1] + 1 (a[i] > 0),否则就是与后一个颜色不同,方案*25。第一次颜色相同的26种方案。
#include <bits/stdc++.h> typedef long long ll;
const int N = 1e5 + 5;
const int MOD = 1e9 + 7;
int a[N]; int main() {
int T; scanf ("%d", &T);
while (T--) {
int n; scanf ("%d", &n);
for (int i=1; i<n; ++i) {
scanf ("%d", a+i);
}
a[n] = 0;
int ans = 26;
for (int i=n-1; i>=1; --i) {
if (a[i] == 0) {
ans = 1ll * ans * 25 % MOD;
} else if (a[i] != a[i+1] + 1) {
ans = 0;
break;
}
}
printf ("%d\n", ans);
} return 0;
}
最短路 1002 Shortest Path
多加了3条边,6个点分别看成起点跑SPFA,然后原来的距离是abs (u - v),取最小值
#include <bits/stdc++.h> const int N = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int a[6], d[6][N], z[N];
bool vis[N];
std::vector<int> G[N];
int n, m; void add_edge(int u, int v) {
G[u].push_back (v);
G[v].push_back (u);
} void SPFA(int k, int s) {
memset (d[k], INF, sizeof (d[k]));
memset (vis, false, sizeof (vis));
d[k][s] = 0; vis[s] = true;
std::queue<int> que; que.push (s);
while (!que.empty ()) {
int u = que.front (); que.pop ();
for (auto v: G[u]) {
if (vis[v]) continue;
d[k][v] = d[k][u] + 1;
vis[v] = true;
que.push (v);
}
}
} int main() {
int T; scanf ("%d", &T);
while (T--) {
scanf ("%d%d", &n, &m);
for (int i=1; i<=n; ++i) {
G[i].clear ();
}
for (int i=1; i<n; ++i) {
add_edge (i, i+1);
}
for (int i=0; i<3; ++i) {
int u, v; scanf ("%d%d", &u, &v);
add_edge (u, v);
a[i*2] = u; a[i*2+1] = v;
}
for (int i=0; i<6; ++i) {
SPFA (i, a[i]);
}
for (int i=0; i<m; ++i) {
int u, v; scanf ("%d%d", &u, &v);
if (u > v) std::swap (u, v);
int &best = z[i];
best = v - u;
for (int i=0; i<6; ++i) {
best = std::min (best, d[i][u] + d[i][v]);
}
}
int ans = 0;
for (int i=0; i<m; ++i) {
ans = (ans + 1ll * (i + 1) * z[i]) % MOD;
}
printf ("%d\n", ans);
} return 0;
}
二进制 + BFS 1003 Transform
s -> t = s ^ t = x,所以要预处理出0到x的最小步骤,翻转某一位可以转换为^ (1<<i)
#include <bits/stdc++.h> const int N = 30;
const int MAX = (1 << 17);
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int a[N], d[MAX];
bool vis[N];
int n, m; void BFS(int s) {
std::queue<int> que; que.push (s);
memset (d, INF, sizeof (d)); d[s] = 0;
while (!que.empty ()) {
int x = que.front (); que.pop ();
for (int i=1; i<=n; ++i) {
int y = x ^ a[i];
if (y > MAX) break;
if (d[y] < INF) continue;
d[y] = d[x] + 1;
que.push (y);
}
}
} int main() {
int T; scanf ("%d", &T);
while (T--) {
scanf ("%d%d", &n, &m);
a[0] = 0;
for (int i=1; i<=n; ++i) {
scanf ("%d", a+i);
}
int k = 0;
for (int k=0; k<100; ++k) {
int x = 1 << k;
if (x > MAX) break;
a[++n] = x;
}
BFS (0);
int ans = 0;
for (int i=0; i<m; ++i) {
int s, t; scanf ("%d%d", &s, &t);
int q = s ^ t;
ans = (ans + 1ll * (i + 1) * d[q]) % MOD;
}
printf ("%d\n", ans);
} return 0;
}
1004 Toposort
待补