51nod 1318 最大公约数与最小公倍数方程组

来源:互联网 发布:软件测试简单吗 编辑:程序博客网 时间:2024/06/06 05:40

原题链接.

题解:

首先分解质因数,gcd就相当于指数的min,lcm就相当于指数的max。

于是问题变成了这样:
给出一坨类似于以下的限制:
min(a,b) = c
max(a,b) = c
问是否有解?

以min为例.

min(a,b) = c
即(a >= c) and (b >= c) and (a = c or b = c)

注意到指数是很小的,c不超过三十。

于是可以把x拆成31(0->30)个组,每个点再拆2个,xi表示x<=i的布尔值,xi就是x>i的布尔值,这两个刚好必须选一个。

xi一定要向xi+1连边,xi也一定要向xi1连边。
a>=c,所以ai->ac1(0<=i<c)
b>=c,同理。
a = c or b = c,因为已经有了a>=c and b >= c,可以看成a <= c or b <= c,
所以ai->bc(i>c),bi->ac(i>c)

然后跑过Trjan判断一下有没有xixi在一个强联通分量里即可。

Code:

#include<set>#include<cstdio>#include<algorithm>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define max(a, b) ((a) > (b) ? (a) : (b))#define min(a, b) ((a) < (b) ? (a) : (b))using namespace std;const int N = 1e6;bool bz[N + 5]; int p[N];char S[N];int T, n, m, a[N], b[N], c[N];int u[50], v[50];int next[N], to[N], final[N], tot;int num[205][105][2], tt, mx;void Shai() {    fo(i, 2, N)  {        if(!bz[i]) p[++ p[0]] = i;        fo(j, 1, p[0]) {            int k = i * p[j];            if(k > N) break;            bz[k] = 1;            if(i % p[j] == 0) break;        }    }}void Fen(int x) {    u[0] = 0;    for(int i = 1; p[i] * p[i] <= x; i ++)        if(x % p[i] == 0) {            u[++ u[0]] = p[i], v[u[0]] = 0;            while(x % p[i] == 0)                x /= p[i], v[u[0]] ++;        }    if(x > 1) u[++ u[0]] = x, v[u[0]] = 1;}int Q_z(int x, int y) {    int z = 0; while(x % y == 0) x /= y, z ++;    return z;}set<int> s;void Clear() {    fo(i, 1, tot) next[i] = 0;    fo(i, 1, tt) final[i] = 0;    tot = 0;}void link(int x, int y) {    next[++ tot] = final[x], to[tot] = y, final[x] = tot;}int z[N], dfn[N], low[N], ff[N], d[N], bd[N], td;void dg(int x) {    bd[x] = 1; d[++ d[0]] = x;    dfn[x] = low[x] = ++ td;    for(int i = final[x]; i; i = next[i])  {        int y = to[i];        if(!dfn[y]) dg(y), low[x] = min(low[x], low[y]); else        if(bd[y]) low[x] = min(low[x], dfn[y]);    }    if(low[x] == dfn[x]) {        for(; d[d[0]] != x; d[0] --)            ff[d[d[0]]] = x, bd[d[d[0]]] = 0;        d[0] --; ff[x] = x; bd[x] = 0;    }}bool pd() {    td = 0;    fo(i, 1, tt) low[i] = 0, dfn[i] = 0;    fo(i, 1, tt) if(!dfn[i])        dg(i);    fo(i, 1, n) fo(j, 0, mx) {        if(ff[num[i][j][0]] == ff[num[i][j][1]]) {            return 0;        }    }    return 1;}char get() {    char c = ' '; for(;c != 'G' && c != 'L'; c = getchar());    return c;}int main() {    Shai();    for(scanf("%d", &T); T; T --) {        s.clear();        scanf("%d %d", &n, &m);        fo(i, 1, m) {            S[i] = get();            scanf("%d %d %d", &a[i], &b[i], &c[i]);            a[i] ++; b[i] ++;            Fen(c[i]);            fo(i, 1, u[0]) s.insert(u[i]);        }        int ans = 1;        while(!s.empty()) {            int x = *s.begin(); s.erase(x);            mx = 0;            fo(i, 1, m) z[i] = Q_z(c[i], x), mx = max(mx, z[i]);            tt = 0; fo(i, 1, n) fo(j, 0, mx) num[i][j][0] = ++ tt, num[i][j][1] = ++ tt;            fo(i, 1, n) fo(j, 0, mx - 1) link(num[i][j][0], num[i][j + 1][0]);            fo(i, 1, n) fo(j, 1, mx) link(num[i][j][1], num[i][j - 1][1]);            Clear();            fo(i, 1, m) {                if(S[i] == 'G') {                    fo(j, 0, z[i] - 1) {                        link(num[a[i]][j][0], num[a[i]][j][1]);                        link(num[b[i]][j][0], num[b[i]][j][1]);                    }                    fo(j, z[i], mx) {                        link(num[a[i]][j][1], num[b[i]][z[i]][0]);                        link(num[b[i]][j][1], num[a[i]][z[i]][0]);                    }                } else {                    fo(j, z[i], mx) {                        link(num[a[i]][j][1], num[a[i]][j][0]);                        link(num[b[i]][j][1], num[b[i]][j][0]);                    }                    fo(j, 0, z[i] - 1) {                        link(num[a[i]][j][0], num[b[i]][z[i] - 1][1]);                        link(num[b[i]][j][0], num[a[i]][z[i] - 1][1]);                    }                }            }            ans &= pd();            if(!ans) break;        }        if(ans) printf("Solution exists\n"); else printf("Solution does not exist\n");    }}
原创粉丝点击