zoukankan      html  css  js  c++  java
  • Codeforces Round #519

    题目链接:传送门

     

    A. Elections (思维+暴力)

    思路:

      从最小的k开始枚举就好了- -。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 100 + 5;
    
    int a[MAX_N];
    
    int main()
    {
        int N;
        cin >> N;
        int m = -1, sum = 0;
        for (int i = 1; i <= N; i++) {
            scanf("%d", a+i);
            m = max(m, a[i]);
            sum += a[i];
        }
        int ans = m;
        int Awruk = N*m-sum;
        while (Awruk <= sum) {
            Awruk += N;
            ans++;
        }
        cout << ans << endl;
        return 0;
    }
    View Code

    B. Lost Array (暴力枚举)

    思路:

      把差分预处理出来,枚举长度,可以跑到最后的就加入答案。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 1e3 + 5;
    
    int a[MAX_N];
    int b[MAX_N];
    int ans[MAX_N];
    
    int main()
    {
        int N;
        cin >> N;
        a[0] = 0;
        for (int i = 1; i <= N; i++) {
            scanf("%d", a+i);
            b[i] = a[i] - a[i-1];
        }
        int cnt = 0;
        for (int i = 1; i <= N; i++) {
            int j;
            for (j = 1; j <= N; j++) {
                if (b[j] != b[(j-1)%i+1])
                    break;
            }
            if (j == N+1)
                ans[cnt++] = i;
        }
        cout << cnt << endl << ans[0];
        for (int i = 1; i < cnt; i++)
            cout << ' ' << ans[i];
        cout << endl;
        return 0;
    }
    View Code

    C. Smallest Word (思维)

    思路:

      遇到连续的a就找到最后一个,翻转

      遇到连续的b也找到最后一个,如果下一个是a,翻转

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 1e3 + 5;
    
    bool ans[MAX_N];
    
    int main()
    {
        string s;
        memset(ans, false, sizeof ans);
        cin >> s;
        int len = s.size();
        int i = 0;
        while (i < len) {
            while (i < len && s[i] == 'a')
                i++;
            ans[i-1] = true;
            while (i < len && s[i] == 'b')
                i++;
            if (i < len && s[i] == 'a')
                ans[i-1] = true;
        }
        cout << ans[0];
        for (int i = 1; i < len; i++)
            cout << ' ' << ans[i];
        cout << endl;
        return 0;
    }
    View Code

    D. Mysterious Crime (尺取+暴力)

    思路:

      从第一行开始,往下面几行找最长的匹配。每行从上一行的最左端的数开始往右匹配,匹配到不同的就break,进入下一行。

      预处理一个pos[i][j],表示第i行的值为j的数在哪个位置。

      找完最后一行后得到最长的匹配的长度为len,计算len对答案产生的贡献

      注意M为1的时候不能匹配特判一下答案就是N*(N+1)/2。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 1e5 + 5;
    const int MAX_M = 10 + 3;
    
    int N, M;
    int a[MAX_M][MAX_N];
    int pos[MAX_M][MAX_N];
    bool vis[MAX_N];
    
    int main()
    {
        cin >> N >> M;
        memset(vis, false, sizeof vis);
        for (int i = 1; i <= M; i++)
            for (int j = 1; j <= N; j++) {
                scanf("%d", &a[i][j]);
                pos[i][a[i][j]] = j;
            }
        long long ans = 0;
        for (int i = 1; i <= N; i++) if (!vis[a[1][i]]){
            int l = i, r = N;
            long long len = 1;
            for (int j = 2; j <= M; j++) {
                int nxtl, nxtr;
                nxtl = nxtr = pos[j][a[j-1][l]];
                while (l <= r && nxtr <= N && a[j][nxtr] == a[j-1][l]) {
                    l++;
                    nxtr++;
                }
                l = nxtl, r = nxtr-1;
                if (j == M) {
                    len = r-l+1;
                    for (int k = l; k <= r; k++)
                        vis[a[M][k]] = true;
                }
            }
            ans += (len+1)*len/2;
        }
        if (M == 1)
            ans = (long long)(N+1)*N/2;
        cout << ans << endl;
        return 0;
    }
    View Code

    E. Train Hard, Win Easy(思维+排序)

    思路:

      两个人(u,v)组队时他们的得分是min(xu+yv,xv+yu),考虑到:

        xu+yv  xv+yu

      =>yv-xv  yu-xu

      令di = yi-xi,则组队时d小的一方出y,d大的一方出x。

      根据d排序后,对于(1 ≤ i < j N)有di dj,所以第i个人和第j个人组队的得分为yi+xj

      预处理x和y的前缀和,对于第i个人,他与在他之前的人组队的得分为:

        $sum_{j=1}^{i-1}y_{j}$ + xi * (i-1);

      与在他之后的人组队的得分为:

        $sum_{j=i+1}^{N}x_{j}$ + yi * (N-i);

      这样可以O(1)算出每个人的得分,然后再减去不能和自己比赛的人的贡献就好了。

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAX_N = 3e5 + 5;
    
    struct Node{
        int ind;
        ll x, y;
        ll d;
        Node(int _i = 0, ll _x = 0, ll _y = 0) : ind(_i), x(_x), y(_y) {d = y-x;}
        bool operator < (const Node& a) const {
            return d < a.d;
        }
    }nodes[MAX_N];
    
    ll sumx[MAX_N], sumy[MAX_N];
    ll ans[MAX_N];
    
    int main()
    {
        int N, M;
        cin >> N >> M;
        memset(ans, 0, sizeof ans);
        for (int i = 1; i <= N; i++) {
            ll x, y;
            scanf("%I64d%I64d", &x, &y);
            nodes[i] = Node(i, x, y);
        }
        for (int i = 1; i <= M; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            ll tmp = 0;
            if (nodes[u] < nodes[v])
                tmp = nodes[u].y + nodes[v].x;
            else
                tmp = nodes[v].y + nodes[u].x;
            ans[u] -= tmp;
            ans[v] -= tmp;
        }
        sort(nodes+1, nodes+1+N);
        sumx[0] = sumy[0] = 0;
        for (int i = 1; i <= N; i++) {
            sumx[i] = sumx[i-1] + nodes[i].x;
            sumy[i] = sumy[i-1] + nodes[i].y;
        }
        for (int i = 1; i <= N; i++) {
            Node cur = nodes[i];
            ans[cur.ind] += sumy[i-1] + cur.x*(i-1);
            ans[cur.ind] += sumx[N] - sumx[i] + cur.y*(N-i);
        }
        bool firstprint = true;
        for (int i = 1; i <= N; i++) {
            if (firstprint)
                firstprint = false;
            else
                printf(" ");
            printf("%I64d", ans[i]);
        }
        puts("");
        return 0;
    }
    View Code

     

    F. Make It One(组合数学+数论+dp)

    思路:

      说实话这题比较玄学。

      2 * 3 * 5 * 7 * 11 * 13 * 17 ≈ 5e5,所以3e5范围内一个数最多有6个质因数。所以答案是不会超过6的,考虑从1开始枚举答案。

    状态:

      f[i][j]表示选择的数字数量为i时,最大公约数为j的方案数,若f[i][1] > 0,就说明符合题意,直接输出。

      已知所有的ai中j的倍数有cnt[j]个,则由容斥原理知:

    状态转移方程:

      f[i][j] = $C_{cnt[j]}^{i}-sum_{k=2}^{infty}f[i][k*j]$

    组合数预处理一个逆元可以O(1)求出,总时间复杂度为O(loga * (N + a))

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 3e5 + 5;
    const int MOD = 1e9 + 7;
    
    int fpow(int a, int p) {
        int ans = 1;
        while (p) {
            if (p&1) ans = (1LL * ans * a) % MOD;
            p >>= 1;
            a = (1LL * a * a) % MOD;
        }
        return ans;
    }
    
    int N;
    int a[MAX_N];
    int f[20][MAX_N], cnt[MAX_N];
    int fac[MAX_N], inv[MAX_N];
    
    int newton(int m, int n) {
        if (n < 0 || m < n) return 0;
        return ((1LL * fac[m] * inv[n])%MOD * inv[m-n]) % MOD;
    }
    
    void init() {
        fac[0] = 1;
        for (int i = 1; i <= MAX_N; i++)
            fac[i] = (1LL * fac[i-1] * i) % MOD;
    
        inv[MAX_N-1] = fpow(fac[MAX_N-1], MOD-2);
        for (int i = MAX_N-1; i >= 1; i--)
            inv[i-1] = (1LL * inv[i] * i) % MOD;
    }
    
    void sub(int& a, int b) {
        a -= b;
        if (a < 0)
            a += MOD;
    }
    
    int main()
    {
        init();
        scanf("%d", &N);
        memset(cnt, 0, sizeof cnt);
        for (int i = 1; i <= N; i++) {
            scanf("%d", a+i);
            cnt[a[i]]++;
        }
        for (int i = 1; i < MAX_N; i++) {
            for (int j = 2*i; j < MAX_N; j += i) {
                cnt[i] += cnt[j];
            }
        }
        for (int i = 1; i < 20; i++) {
            for (int j = MAX_N-1; j >= 1; j--) {
                f[i][j] = newton(cnt[j], i);
                for (int k = j+j; k < MAX_N; k += j)
                    sub(f[i][j], f[i][k]);
            }
            if (f[i][1] > 0) {
                printf("%d
    ", i);
                return 0;
            }
        }
        puts("-1");
        return 0;
    }
    View Code
  • 相关阅读:
    vim高级编辑(一)
    [每日一题] 11gOCP 1z0-052 :2013-09-5 runInstaller oracle of no swap
    ABAP 中 Table Control例子
    跟我一起学习ASP.NET 4.5 MVC4.0(四)
    跟我一起学习ASP.NET 4.5 MVC4.0(三)
    跟我一起学习ASP.NET 4.5 MVC4.0(二)
    跟我一起学习ASP.NET 4.5 MVC4.0(一)
    如何选择Html.RenderPartial和Html.RenderAction
    ASP.NET MVC4 Razor
    ADO.NET Entity Framework -Code Fisrt 开篇(一)
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9916943.html
Copyright © 2011-2022 走看看