zoukankan      html  css  js  c++  java
  • 2020 Multi-University Training Contest 4

    Contest Info


    传送门

    Solved A B C D E F G H I J K L
    8 / 12 - O Ø O O - Ø - Ø - O Ø
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    B. Blow up the Enemy

    签到。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/30 12:48:55
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    const double eps = 1e-7;
    void run() {
        int n;
        cin >> n;
        vector<int> a(n), d(n);
        vector<int> t(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i] >> d[i];
            int nd = (100 + a[i] - 1) / a[i];
            t[i] = (nd - 1) * d[i];
        }
        double ans = 0;
        for (int i = 0; i < n; i++) {
            double res = 0;
            for (int j = 0; j < n; j++) {
                if (fabs(t[i] - t[j]) < eps) {
                    res += 0.5;
                } else if (t[i] > t[j] + eps) {
                } else {
                    res += 1;
                }
            }
            res /= 1.0 * n;
            ans = max(ans, res);
        }
        cout << ans << '
    ';
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(10);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    C. Contest of Rope Pulling

    直接随机一下,然后一个是正贡献、一个是负贡献,做个背包就行,可以设定一个上限大概为根号级别。应该就可以过了。。

    D. Deliver the Cake

    跑个带有两个附加状态的最短路就行。

    E. Equal Sentences

    dp一下。

    Code
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    typedef long double ld;
    const int MAXN = 1e5 + 5, MAXM = 4e5 + 5, BOUND = 2e5, MOD = 1e9+7, INF = 0x3f3f3f3f, base = 10000;
    const int inv2 = (MOD + 1) >> 1;
    const ll INFL = 0x3f3f3f3f3f3f3f3f;
    const double PI = acos(-1.0), eps = 1e-9;
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    #define mid l+((r-l)>>1)
    #define lc(x) ch[x][0]
    #define pii pair<int,int>
    #define vi vector<int>
    #define vii vector<pair<int,int>>
    #define rc(x) ch[x][1]
    #define random(a,b) ((a)+rand()%((b)-(a)+1))
    #define all(a) (a).begin(), (a).end()
    #define sz(a) int(a.size())
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fi first
    #define se second
    #define MP std::make_pair
    #define ri register int
    //#define sz(a) int((a).size())
    inline int add(int a, int b) {return a + b >= MOD ? a + b - MOD : a + b;}
    inline int dec(int a, int b) {return a < b ? a - b + MOD : a - b;}
    inline int mul(int a, int b) {return 1ll * a * b % MOD;}
    template <typename T>
    inline void cmin(T &a,T b){a = min(a,b);}
    template <typename T>
    inline void cmax(T &a,T b){a = max(a,b);}
    ll qpow(ll a,ll b){
        ll ans=1;
        for(;b;b>>=1,a=a*a%MOD)if(b&1)ans=ans*a%MOD;
        return ans;
    }
    mt19937 mrand(random_device{}());
    
    string s[MAXN];
    int f[MAXN];
    void run(){
        int n; cin>>n;
        rep(i,1,n){
            cin>>s[i];
        }
        f[0] = 1;
        rep(i,1,n){
            f[i] = f[i-1];
            if(s[i] != s[i-1])f[i] = add(f[i], f[i-2]);
        }
        cout<<f[n]<<'
    ';
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        int _=1;
        cin>>_;
        while(_--)run();
        return 0;
    }
    

    G. Go Running

    考虑建图,从左往右的情况连边,会有若干条链;从右往左也是。并且链的斜率都为正负1。
    那么考虑将这个图旋转一下变为网格图,要求的就是选择最少的行、列来覆盖这个网格图。这就是一个最小点覆盖的问题。
    使用dinic跑最大流复杂度为(O(nsqrt{n})),并且上界也比较松。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/30 14:08:31
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    void err(int x) {cerr << x;}
    void err(long long x) {cerr << x;}
    void err(double x) {cerr << x;}
    void err(char x) {cerr << '"' << x << '"';}
    void err(const string &x) {cerr << '"' << x << '"';}
    void _print() {cerr << "]
    ";}
    template<typename T, typename V>
      void err(const pair<T, V> &x) {cerr << '{'; err(x.first); cerr << ','; err(x.second); cerr << '}';}
    template<typename T>
      void err(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), err(i); cerr << "}";}
    template <typename T, typename... V>
      void _print(T t, V... v) {err(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
    #ifdef Local
    #define dbg(x...) cerr << "[" << #x << "] = ["; _print(x)
    #else
    #define dbg(x...)
    #endif
    const int N = 4e5 + 5;
    
    int n;
    template <class T>
    struct Dinic{
        struct Edge{
            int v, next;
            T flow;
            Edge(){}
            Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
        }e[N << 1];
        int head[N], tot;
        int dep[N];
        void init() {
            memset(head, -1, sizeof(int) * (2 * n + 10)); tot = 0;
        }
        void adde(int u, int v, T w, T rw = 0) {
            e[tot] = Edge(v, head[u], w);
            head[u] = tot++;
            e[tot] = Edge(u, head[v], rw);
            head[v] = tot++;
        }
        bool BFS(int _S, int _T) {
            memset(dep, 0, sizeof(dep));
            queue <int> q; q.push(_S); dep[_S] = 1;
            while(!q.empty()) {
                int u = q.front(); q.pop();
                for(int i = head[u]; ~i; i = e[i].next) {
                    int v = e[i].v;
                    if(!dep[v] && e[i].flow > 0) {
                        dep[v] = dep[u] + 1;
                        q.push(v);
                    }
                }
            }
            return dep[_T] != 0;
        }
        T dfs(int _S, int _T, T a) {
            T flow = 0, f;
            if(_S == _T || a == 0) return a;
            for(int i = head[_S]; ~i; i = e[i].next) {
                int v = e[i].v;
                if(dep[v] != dep[_S] + 1) continue;
                f = dfs(v, _T, min(a, e[i].flow));
                if(f) {
                    e[i].flow -= f;
                    e[i ^ 1].flow += f;
                    flow += f;
                    a -= f;
                    if(a == 0) break;
                }
            }
            if(!flow) dep[_S] = -1;
            return flow;
        }
        T dinic(int _S, int _T) {
            T max_flow = 0;
            while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
            return max_flow;
        }
    };
    
    Dinic<int> solver;
    
    void run() {
        cin >> n;
        map<int, vector<int>> lr, rl;  
        for (int i = 0; i < n; i++) {
            int t, x;
            cin >> t >> x;
            lr[x - t].push_back(i + 1);
            rl[x + t].push_back(i + 1);
        }
        // y = x + c
        // x2 - x1 = t2 - t1
        // y = -x + c
        // x2 - x1 = t1 - t2
        vector<int> x(n + 1), y(n + 1);
        int tx = 1, ty;
        for (auto& it : lr) {
            for (auto& it2 : it.se) {
                x[it2] = tx;
            }
            ++tx;
        }
        ty = tx;
        for (auto& it : rl) {
            for (auto& it2 : it.se) {
                y[it2] = ty;
            }
            ++ty;
        }
        int S = 0, T = ty;
        solver.init();
        for (int i = 1; i < tx; i++) {
            solver.adde(S, i, 1);
        }
        for (int i = tx; i < ty; i++) {
            solver.adde(i, T, 1);
        }
        for (int i = 1; i <= n; i++) {
            solver.adde(x[i], y[i], 1);
        }
        int ans = solver.dinic(S, T);
        cout << ans << '
    ';
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    I. Imperative Meeting

    题意:
    给定一颗无根树,在上面放置(m)个人,然后他们会走到某个点上面去,代价为所有人经过的边数之和。
    一共会有(nchoose m)种情况,现在要计算所有情况代价最小的和为多少。

    思路:
    显然直接算十分麻烦,因为枚举重心的话会涉及很多情况。所以转化一下思维:

    • 考虑每一条边的贡献。

    对于一条边来说,假设一边有(x)个人,另外一边有(y)个人,(x<y),那么最优方案一定会贡献(min(x,y)=x)次,此时我们取树的重心为带权重心即可。
    那么可以列出式子:

    [f(s)=sum_{i=0}^m{schoose i}{n-schoose m-i}cdot min(i, m-i) ]

    这就是题解中的式子,因为式子中含有min,我们可以直接将其拆开,就有题解中的式子(令(p=frac{m-1}{2})):

    [f(s)=sum_{i=1}^p({schoose i}{n-schoose m-i}cdot i+{schoose m-i}{n-schoose i}cdot i)+[m\% 2]cdot {schoose m/2}{n-schoose m/2}cdot(m/2) ]

    后面那一部分暂时不用管,前面的两部分其实是具有对称性,我们令(s'=n-s)即可很轻松发现是具有对称关系的。
    因此我们先考虑前一部分:(displaystyle g(s)=sum_{i=1}^p{schoose i}{n-schoose m-i}cdot i),显然后面就等于(g(n-s))
    我们可以把(i)消去:(displaystyle g(s)=scdot sum_{i=1}^p{s-1choose i-1}{n-schoose m - i})
    我们可以给其赋予组合意义,就是(n-1)个盒子要放(m-1)个小球,前面(s-1)个位置最多放(p-1)个小球的方案数。
    因为最后答案是跟(s)有关,注意这是一个前缀,其它数不会改变,那么就可以通过递推求得所有的(g(s))
    剩下的就简单了。

    Code
    // Author : heyuhhh
    // Created Time : 2020/08/06 10:41:24
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    void err(int x) {cerr << x;}
    void err(long long x) {cerr << x;}
    void err(double x) {cerr << x;}
    void err(char x) {cerr << '"' << x << '"';}
    void err(const string &x) {cerr << '"' << x << '"';}
    void _print() {cerr << "]
    ";}
    template<typename T, typename V>
      void err(const pair<T, V> &x) {cerr << '{'; err(x.first); cerr << ','; err(x.second); cerr << '}';}
    template<typename T>
      void err(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), err(i); cerr << "}";}
    template <typename T, typename... V>
      void _print(T t, V... v) {err(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
    #ifdef Local
    #define dbg(x...) cerr << "[" << #x << "] = ["; _print(x)
    #else
    #define dbg(x...)
    #endif
    //head
    const int N = 1e6 + 5, MOD = 1e9 + 7;
    
    int qpow(ll a, ll b) {
        ll res = 1;
        while(b) {
            if(b & 1) res = res * a % MOD;
            a = a * a % MOD;
            b >>= 1;   
        }
        return res;   
    }
    int fac[N], inv[N];
    void init() {
        fac[0] = 1;
        for(int i = 1; i < N; i++) fac[i] = 1ll * fac[i - 1] * i % MOD;
        inv[N - 1] = qpow(fac[N - 1], MOD - 2);
        for(int i = N - 2; i >= 0; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % MOD;
    }
    
    int C(int n, int m) {
        if (n < m || n < 0 || m < 0) return 0;
        return 1ll * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    
    void add(int& x, int y) {
        x += y;
        if (x >= MOD) x -= MOD;
    }
    
    int f[N], sz[N];
    int n, m;
    int ans[N];
    
    void run() {
        cin >> n >> m;
        for (int i = 2; i <= n; i++) {
            cin >> f[i];
        }
        int p = (m - 1) / 2;
        ans[1] = C(n - 1, m - 1);
        for (int i = 2; i <= n; i++) {
            int t = 1ll * C(i - 2, p - 1) * C(n - i, m - 1 - p) % MOD;
            ans[i] = (ans[i - 1] - t + MOD) % MOD;
        }
        if (p == 0) {
            for (int i = 1; i <= n; i++) {
                ans[i] = 0;
            }
        }
        for (int i = 1; 2 * i <= n; i++) {
            ans[i] = 1ll * ans[i] * i % MOD + 1ll * ans[n - i] * (n - i) % MOD;
            ans[i] %= MOD;
        }
        for (int i = 1; i <= n; i++) {
            sz[i] = 1;
        }
        for (int i = n; i > 1; i--) {
            sz[f[i]] += sz[i];
        }
        int res = 0;
        for (int i = 1; i <= n; i++) {
            int s = sz[i];
            if (s < n) {
                add(res, ans[min(s, n - s)]);
                if (m % 2 == 0) {
                    int tmp = 1ll * (m / 2) * C(s, m / 2) % MOD * C(n - s, m / 2) % MOD;
                    add(res ,tmp);
                }
            }
        }
        cout << res << '
    ';
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        init();
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    K. Kindergarten Physics

    引力没啥影响,所以直接输出。

    L. Last Problem

    考虑递归进行构造,但是如果直接硬上的话可能时间会炸掉。但是稍微手模一下就会发现有很多共用的部分是不用管的,这样就节约掉了很大的时间。所以对于位置记忆化一下就行。当然还要选择一个较优的策略,但是这个策略其实挺多的。
    相减代码:

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/30 20:05:17
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 5000 + 5;
    int mp[N][N];
    void run() {
        int n;
        cin >> n;
        vector<pair<pii, int>> ans;
        function <void(int, int, int)> draw = [&] (int x, int y, int n) {
            if (mp[x][y] == n) return;
            if (n <= 0) return;
            if (n == 1) {
                ans.emplace_back(MP(MP(x, y), 1));
                mp[x][y] = 1;
                return;
            }
            draw(x, y + 1, n - 1);
            draw(x - 1, y, n - 2);
            draw(x + 1, y, n - 3);
            draw(x, y - 1, n - 4);
            ans.emplace_back(MP(MP(x, y), n));
            mp[x][y] = n;
            return;
        };
        draw(2000, 2000, n);
        for (auto it : ans) {
            cout << it.fi.fi << ' ' << it.fi.se << ' ' << it.se << '
    ';
        }
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    [LeetCode] Valid Palindrome
    [LeetCode] Word Ladder II(bfs、dfs)
    [LeetCode] Word Ladder
    [LeetCode] Longest Consecutive Sequence(DP)
    [LeetCode] Binary Tree Maximum Path Sum(递归)
    [LeetCode] Search in Rotated Sorted Array II
    hadoop streaming map输入文件路径获取
    LeetCode 4. 寻找两个正序数组的中位数
    剑指 Offer 56
    LeetCode 260.只出现一次的数字 III
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/13463011.html
Copyright © 2011-2022 走看看