zoukankan      html  css  js  c++  java
  • 省选测试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;
    }
    
  • 相关阅读:
    NSPredicate的用法、数组去重、比较...
    CocoaPods安装和使用教程
    UITableView学习笔记
    Linux dpkg 命令
    Linux rpm 软件包管理命令
    Linux chmod 文件权限命令
    Linux vi 命令
    分库分表背后那些事儿
    Spring Cloud Feign原理及性能
    linux "No space left on device" 磁盘空间解决办法
  • 原文地址:https://www.cnblogs.com/shawk/p/14420282.html
Copyright © 2011-2022 走看看