13158:千钧一发

#include <cmath>
#include <cstdio>
#include <cstring>

typedef long long lnt;

const int siz = 1000005;
const int inf = 1000000007;

int n;
int a[siz];
int b[siz];

int tot;
int s, t;
int hd[siz];
int to[siz];
int fl[siz];
int nt[siz];

inline void add(int u, int v, int f)
{
    nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
    nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
}

int dep[siz];

inline bool bfs(void)
{
    static int que[siz];
    static int head, tail;

    memset(dep, 0, sizeof(dep));
    head = 0, tail = 0;
    que[tail++] = s;
    dep[s] = 1;

    while (head != tail)
    {
        int u = que[head++], v;

        for (int i = hd[u]; ~i; i = nt[i])
            if (!dep[v = to[i]] && fl[i])
                dep[que[tail++] = v] = dep[u] + 1;
    }

    return dep[t];
}

int cur[siz];

int min(int a, int b)
{
    return a < b ? a : b;
}

int dfs(int u, int f)
{
    if (u == t || !f)
        return f;

    int used = 0, flow, v;

    for (int i = cur[u]; ~i; i = nt[i])
        if (dep[v = to[i]] == dep[u] + 1 && fl[i])
        {
            flow = dfs(v, min(f - used, fl[i]));

            used += flow;
            fl[i] -= flow;
            fl[i^1] += flow;

            if (used == f)
                return f;

            if (fl[i])
                cur[u] = i;
        }

    if (!used)
        dep[u] = 0;

    return used;
}

inline int maxFlow(void)
{
    int maxFlow = 0, newFlow;

    while (bfs())
    {
        for (int i = s; i <= t; ++i)
            cur[i] = hd[i];

        while (newFlow = dfs(s, inf))
            maxFlow += newFlow;
    }

    return maxFlow;
}

inline lnt sqr(lnt x)
{
    return x * x;
}

int gcd(int x, int y)
{
    return y ? gcd(y, x % y) : x;
}

inline bool check(int x, int y)
{
    if (gcd(x, y) != 1)
        return false;

    lnt t = sqr(x) + sqr(y);
    if (sqr(sqrt(t)) != t)
        return false;

    return true;
}

signed main(void)
{
    scanf("%d", &n);

    for (int i = 1; i <= n; ++i)
        scanf("%d", a + i);

    for (int i = 1; i <= n; ++i)
        scanf("%d", b + i);

    s = 0, t = n + 1;

    memset(hd, -1, sizeof(hd));

    for (int i = 1; i <= n; ++i)
        if (a[i] & 1)
            add(s, i, b[i]);
        else
            add(i, t, b[i]);

    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            if (a[i] & 1)if (!(a[j] & 1))
                if (check(a[i], a[j]))
                    add(i, j, inf);

    int sum = 0;

    for (int i = 1; i <= n; ++i)
        sum += b[i];

    printf("%d\n", sum - maxFlow());
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值