zoukankan      html  css  js  c++  java
  • 【Nowcoder 1103A】复读数组

    题目大意:

    有一个长为 (n imes k) 的数组,它是由长为 (n) 的数组 (A_1,A_2,cdots,A_n) 重复 (k) 次得到的。
    定义这个数组的一个区间的权值为它里面不同的数的个数,现在,你需要求出对于这个数组的每个非空区间的权值之和。

    正文:

    有一个关键的性质:答案就是每一个数字能做贡献的区间数量之和。那么我们只用枚举最近的两个相同数字,然后用总区间减去两个数字之间的非空子区间个数即可。

    代码:

    const int N = 1e5 + 10;
    const ll mod = 1e9 + 7;
     
    inline ll Read()
    {
        ll x = 0, f = 1;
        char c = getchar();
        while (c != '-' && (c < '0' || c > '9')) c = getchar();
        if (c == '-') f = -f, c = getchar();
        while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
        return x * f;
    }
     
    ll n, t;
    ll m, a[N], ans, b[N];
     
    vector <int> pos[N];
     
    ll Cnt(ll l, ll r)
    {
        return (r - l + 1) * (r - l + 2) % mod * 500000004ll % mod;
    }
     
    int main()
    {
        n = Read(), m = Read();
        for (int i = 1; i <= n; i++) b[i] = a[i] = Read();
        sort (b + 1, b + 1 + n);
        t = unique(b + 1, b + 1 + n) - b - 1;
        for (int i = 1; i <= n; i++) pos[lower_bound(b + 1, b + 1 + t, a[i]) - b].push_back(i);
        for (int i = 1; i <= t; i++)
        {
            int len = pos[i].size();
            ll tmp = 0;
            (tmp += (Cnt(1, pos[i][0] - 1) + Cnt(pos[i][len - 1] + 1, n)) % mod) %= mod;
            for (int j = 1; j < len; j++)
                (tmp += Cnt(pos[i][j - 1] + 1, pos[i][j] - 1) * m % mod) %= mod;
            (tmp += Cnt(pos[i][len - 1] + 1, pos[i][0] + n - 1) * (m - 1) % mod) %= mod;
            ans = (ans + Cnt(1, n * m % mod) - tmp) % mod;
        }
        printf ("%lld
    ", (ans % mod + mod) % mod);
        return 0;
    }
    
  • 相关阅读:
    Yii AR Model 查询
    学习进度4
    学习进度三
    个人每日总结7
    个人每日总结6
    个人每日总结5
    个人每日总结4
    个人冲刺承担的任务项目的用户模板和用户场景模板
    个人每日总结3
    个人每日总结2
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/15337754.html
Copyright © 2011-2022 走看看