• 省选测试25


    A two (Unaccepted)

    题目大意 :

    • 咕咕

    Code

    Show Code

    B bracket (Unaccepted)

    题目大意 :

    • 咕咕

    Code

    Show Code

    C sum

    题目大意 : 从1到n中选一个子集,满足元素间两两互质,最大化子集和

    • 有一个没证明但是感觉很对的结论是答案子集中每个元素质因子分解后不质因子种类最多两个,而且一个小于根号,一个大于根号

    • 那就先只用一种质因子,s给小于根号的质数建边权为0的边,大于根号的质数给t建边权为0的边

    • 然后如果有两个质因子可以更优,那就给这两个点建一条边权位多出来的贡献的边

    • 跑一遍最大费用可行流,再加上一个质数的贡献

    Code

    Show Code
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N = 2e5 + 5;
    
    struct Edge {
        int n, t, f, c;
    }e[N*5];
    int h[N], edc = 1;
    
    void Add(int x, int y, int z) {
        e[++edc] = (Edge) {h[x], y, 1, z}; h[x] = edc;
        e[++edc] = (Edge) {h[y], x, 0,-z}; h[y] = edc;
    }
    
    bool v[N];
    int n, p[N], f[N], tot, sq, ans, d[N];
    
    int Cal(int x, ll y) {
        while (y * x <= n) y *= x;
        return y;
    }
    
    bool Spfa() {
        memset(v + 1, 0, tot);
        memset(d + 1, 0xcf, tot * 4);
        queue<int> q; q.push(1); d[1] = 0;
        while (!q.empty()) {
            int x = q.front(); q.pop();
            for (int i = h[x], y; i; i = e[i].n) {
                if (!e[i].f || d[y=e[i].t] >= d[x] + e[i].c) continue;
                d[y] = d[x] + e[i].c; q.push(y);
            }
        }
        return d[2] > 0;
    }
    
    int Dinic(int x, int lim) {
        if (x == 2) return lim;
        int sum = 0; v[x] = 1;
        for (int i = h[x], y; i && lim; i = e[i].n)
            if (e[i].f && d[y=e[i].t] == d[x] + e[i].c && !v[y])
                if (Dinic(y, 1)) sum++, e[i].f--, e[i^1].f++, ans += e[i].c;
        if (!sum) d[x] = -1e9;
        return sum;
    }
    
    int main() {
        scanf("%d", &n); tot = 2; sq = sqrt(n);
        for (int i = 2; i <= n; ++i) {
            if (!v[i]) {
                p[++tot] = i; 
                f[tot] = Cal(i, i); ans += f[tot];
                if (i <= sq) Add(1, tot, 0);
                else Add(tot, 2, 0);
            }
            for (int j = 3; j <= tot && i * p[j] <= n; ++j) {
                v[i*p[j]] = 1;
                if (i % p[j] == 0) break;
            }
        }
        for (int i = 3; p[i] <= sq; ++i)
            for (int j = tot, tmp; p[j] > sq; --j)
                if ((tmp = Cal(p[i], p[j]) - f[i] - f[j]) > 0)
                    Add(i, j, tmp);
        while (Spfa()) Dinic(1, 1e9);
        printf("%d
    ", ans + 1);
        return 0;
    }
    
  • 相关阅读:
    最大生成树
    Codeforces#363 Div2
    AOJ2249最短路+最小费用
    Codeforces#364Div2
    POJ3268Dijkstra
    POJ3259负环判定
    Codeforces#362
    POJ3169差分约束系统
    POJ3723最小生成树
    hdu 4038 2011成都赛区网络赛H 贪心 ***
  • 原文地址:https://www.cnblogs.com/shawk/p/14420282.html
Copyright © 2020-2023  润新知