1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #include <bits/stdc++.h> using namespace std;
const int N = 2e4 + 5; const int M = 1e5 + 5; const int PRIME = 1e7 + 5; const int CNT = 6e5 + 5;
int T; int n, m, s, t, ans; int b[N], r[N]; int tot, pre[M << 1], to[M << 1], val[M << 1], tail[N];
void addEdge (int u, int v, int w) { to[++tot] = v, val[tot] = w, pre[tot] = tail[u], tail[u] = tot; to[++tot] = u, val[tot] = 0, pre[tot] = tail[v], tail[v] = tot; }
int gcd (int m, int n) { if (m < n) swap(m, n); if (n == 0) return m; return gcd(n, m % n); }
int cnt; int primes[CNT]; void Prework () { bool vis[PRIME] = {0}; for (int i = 2; i * i <= 1e7; ++i) if (!vis[i]) for (int j = i * i; j <= 1e7; j += i) vis[j] = true; for (int i = 2; i <= 1e7; ++i) if (!vis[i]) primes[++cnt] = i; }
namespace MaxFlow { #define INF 0x3f3f3f3f int p[N] = {0}, inc[N]; bool vis[N]; int q[N]; void Init () { memset(p, 0, sizeof(p)), memset(inc, 0, sizeof(inc)); } bool BFS () { memset(vis, false, sizeof(vis)); int head = 0, back = 1; vis[s] = true, inc[s] = INF; q[1] = s; while (head < back) { int nowfront = q[++head]; for (int ind = tail[nowfront]; ind; ind = pre[ind]) { if (!val[ind]) continue ; if (vis[to[ind]]) continue ; inc[to[ind]] = min(inc[nowfront], val[ind]); vis[to[ind]] = true, q[++back] = to[ind], p[to[ind]] = ind; if (to[ind] == t) return true; } } return false; } void Work () { int cur = t; while (cur ^ s) { int las = p[cur]; val[las] -= inc[t], val[las ^ 1] += inc[t]; cur = to[las ^ 1]; } ans += inc[t]; return ; } }
int main() { scanf("%d", &T); Prework(); while (T--) { scanf("%d%d", &n, &m); s = n + m + 1, t = n + m + 2; memset(pre, 0, sizeof(pre)), memset(tail, 0, sizeof(tail)); tot = 1; ans = 0; for (int i = 1; i <= n; ++i) scanf("%d", &b[i]), addEdge(s, i, 1); for (int i = 1; i <= m; ++i) scanf("%d", &r[i]), addEdge(i + n, t, 1); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= cnt; ++j) { if (primes[j] > b[i]) break ; if (b[i] % primes[j] == 0) addEdge(i, j + n + m + 2, 1); } } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= cnt; ++j) { if (primes[j] > r[i]) break ; if (r[i] % primes[j] == 0) addEdge(j + n + m + 2, i + n, 1); } } while (MaxFlow::BFS()) MaxFlow::Work(); printf("%d\n", ans); } return 0; }
|