Loading

ABC 272 E Add and Mex(调和级数 暴力)

E Add and Mex(调和级数 暴力)

题意:

​ 给出一个长度为n\(\le 1e5\)的数组a,每秒对数组中的数加上其下标,例如\(a_i\)在第一秒为\(a_i+i\),第二秒为\(a_i+2i\)。请输出前m\(\le 1e5\)秒中每一秒的最小的非负整数。

思路:

​ 因为只有n个数,那么这个最小非负整数一定小于\(1e5\)。那么当\(a_i\)大于1e5的时候就没有用了,这点很重要。那么我们直接去暴力枚举,把结果存在\(vector<int> flag[秒数]\)中,这个复杂度是调和级数也就是\(O(nlogn)\)的,轻松可以跑过。但是要注意的是,很可能会出现全是-1e9的极端情况,那你枚举的秒数的起点就需要对于这一点作出特判,详情看代码。

实现:

const int N = 200005;
int n, m;
int a[N];
vector<int> flag[N];

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    for (int i = 1; i <= n; i++)
    {
        if(a[i] > n)    continue;
        int st;
        if(a[i] < 0)
            st = (abs(a[i]) / i);
        else 
            st = 1;
        for(int j = st; j <= m; j ++)
        {
            if(a[i] + j * i < 0)    continue;
            if(a[i] + j * i > n)    break;
            flag[j].push_back(a[i] + j * i);
        }
    }

    for (int i = 1; i <= m; i++)
    {
        vector<bool> vis(N, 0);
        for(auto x : flag[i])
            if(x < N)
                vis[x] = 1;

        int res = 0;
        while(vis[res])
            res ++;
        cout << res << '\n';
    }
}
posted @ 2022-10-09 20:53  DM11  阅读(76)  评论(1编辑  收藏  举报