zoukankan      html  css  js  c++  java
  • [CF359D] Pair of Numbers

    [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 << " ";
    }
    
  • 相关阅读:
    WCF webHttpBinding协议上传接收文件
    mysql 用存储过程和函数分别模拟序列
    angular 下载文件
    Firebird 备份与恢复
    sql 等额本息
    Firebird 手动安装 Legacy_Auth 登陆认证
    Firebird 获取用户表及字段
    Firebird shadow
    Linux的安装(虚拟机环境)与基础配置
    第 3 章 数据库系统 3.5备份与恢复
  • 原文地址:https://www.cnblogs.com/mollnn/p/14450810.html
Copyright © 2011-2022 走看看