因为只有奇偶之间有操作, 可以看出是二分图, 然后拆质因子, 二分图最大匹配求答案就好啦。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 5000 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; int odd[N], even[N], ocnt, ecnt; int L[N], R[N]; int G[N][N]; int match[N]; bool vis[N]; int n, m; int path(int u) { for(int v = 1; v <= ecnt; v++) { if(G[u][v] && !vis[v]) { vis[v] = true; if(match[v] == -1 || path(match[v])) { match[v] = u; return 1; } } } return 0; } int main() { memset(match, -1, sizeof(match)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); if(i & 1) { L[i] = ocnt + 1; for(int j = 2; j * j <= x; j++) { if(x % j) continue; while(x % j == 0) { odd[++ocnt] = j; x /= j; } } if(x > 1) odd[++ocnt] = x; R[i] = ocnt; } else { L[i] = ecnt + 1; for(int j = 2; j * j <= x; j++) { if(x % j) continue; while(x % j == 0) { even[++ecnt] = j; x /= j; } } if(x > 1) even[++ecnt] = x; R[i] = ecnt; } } while(m--) { int u, v; scanf("%d%d", &u, &v); if(v & 1) swap(u, v); for(int i = L[u]; i <= R[u]; i++) for(int j = L[v]; j <= R[v]; j++) if(odd[i] == even[j]) G[i][j] = 1; } int ans = 0; for(int i = 1; i <= ocnt; i++) { memset(vis, false, sizeof(vis)); if(path(i)) ans++; } printf("%d\n", ans); return 0; } /* */
Codeforces Round #284 (Div. 1) C. Array and Operations 二分图匹配
原文:https://www.cnblogs.com/CJLHY/p/10351267.html