[CF359D] Pair of Numbers - dp

Description

找到序列中最长的区间,满足区间中有一个数 x 可以整除区间内任意数。\(ai \le 10^6\)

Solution

一种暴力的做法:如果一个数可以整除区间内所有数,他一定是这个区间的 min,同时是这个区间的 gcd。所以,一个区间可行,当且仅当这个区间的 gcd=min。二分答案,用 ST 表季胺盐即可

设 li 表示 i 能整除的区间 \([?,i]\) 的最小的 ?,ri 同理

求这个东西可以递推,如果 i 能整除 \([?,i]\) 那么 i 也能整除 \([l[?],i]\)

所以我们每次往左边试探一位

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 1e6 + 5;
int n, a[N], l[N], r[N], ans;
vector<int> av;

signed main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
    {
        l[i] = i;
        while (a[l[i] - 1] % a[i] == 0 && l[i] > 1)
            l[i] = l[l[i] - 1];
    }
    for (int i = n; i >= 1; i--)
    {
        r[i] = i;
        while (a[r[i] + 1] % a[i] == 0 && r[i] < n)
            r[i] = r[r[i] + 1];
    }
    for (int i = 1; i <= n; i++)
    {
        int tans = r[i] - l[i];
        if (tans > ans)
        {
            ans = tans;
            av = {l[i]};
        }
        else if (tans == ans)
        {
            if (av.size() && l[i] == av.back())
                continue;
            av.push_back(l[i]);
        }
    }
    cout << av.size() << " " << ans << endl;
    for (auto i : av)
        cout << i << " ";
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-10-28
  • 2022-12-23
  • 2022-01-15
  • 2021-05-26
  • 2021-10-06
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-12-14
  • 2022-01-04
  • 2021-11-30
  • 2021-11-21
相关资源
相似解决方案