Codeforces Round #489 (Div. 2) D. Nastya and a Game

题目链接: D. Nastya and a Game

题目大意

一个数组a, 有n个元素, 1 n 2 10 5 , 1 a [ i ] 10 18 , 求有多少区间 [ l , r ] 满足 p s = k , p = i = l r a [ i ] , s = i = l r a [ i ] , k , 1 k 10 5

思路

p s = k p = s k , 因为 p = s k 2 10 5 10 18 10 5 = 2 10 18 ,所以区间中大于1的元素个数应该要小于60( 2 61 2.3 10 18 ), 对于所有l,循环r,当区间p大于 2 18 时,退出循环,l++
为了减小复杂度,记录每个大于等于2的元素位置,当p>=s*k, 要往区间里面加值为1的元素,判断当前位置到下一个大于等于2的元素位置是否有足够的1使得p==s*k,然后r调到下一大于等于2的元素位置继续运行

代码

GNU C++17 Accepted 499 ms 1580 KB

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
const ll MAX = 2E18 + 100;
int n, k, a[maxn];
int pos[maxn], cnt;

int main()
{
    cin >> n >> k;
    for (int i = 0; i < n; ++i)
    {
        cin >> a[i];
        if (a[i] > 1) pos[cnt++] = i;
    }
    pos[cnt++] = n;
    ll s, p, ans = 0;
    for (int l = 0; l < n; ++l)
    {
        s = p = a[l];
        for (int r = l; r < n; )
        {
            int nxt = pos[upper_bound(pos, pos + cnt, r) - pos];
            if (p >= s * k && p % k == 0)
            {
                ll need1 = p / k - s;
                if (nxt - r - 1 >= need1) ++ans;
            }
            if(nxt == n) break;
            s += a[nxt] + nxt - r - 1;
            if (p >= MAX / a[nxt]) break;
            p *= a[nxt];
            r = nxt;
        }
    }
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/litmxs/article/details/80995800