• Codeforces 395 D.Pair of Numbers


    D. Pair of Numbers
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Simon has an array a1, a2, ..., an, consisting of n positive integers. Today Simon asked you to find a pair of integers l, r (1 ≤ l ≤ r ≤ n), such that the following conditions hold:

    1. there is integer j (l ≤ j ≤ r), such that all integers al, al + 1, ..., ar are divisible by aj;
    2. value r - l takes the maximum value among all pairs for which condition 1 is true;

    Help Simon, find the required pair of numbers (l, r). If there are multiple required pairs find all of them.

    Input

    The first line contains integer n (1 ≤ n ≤ 3·105).

    The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 106).

    Output

    Print two integers in the first line — the number of required pairs and the maximum value of r - l. On the following line print all l values from optimal pairs in increasing order.

    Examples
    input
    5
    4 6 9 3 6
    output
    1 3
    2
    input
    5
    1 3 5 7 9
    output
    1 4
    1
    input
    5
    2 3 5 7 11
    output
    5 0
    1 2 3 4 5
    Note

    In the first sample the pair of numbers is right, as numbers 6, 9, 3 are divisible by 3.

    In the second sample all numbers are divisible by number 1.

    In the third sample all numbers are prime, so conditions 1 and 2 are true only for pairs of numbers (1, 1), (2, 2), (3, 3), (4, 4), (5, 5).

    题目大意:给出长度为n的序列a[i],要求找到所有满足下列两个条件的子序列a[l],a[l+1],…,a[r]的个数: 
    1.存在l<=j<=r,使得a[j]是a[l],a[l+1],…,a[r]的最大公因数 
    2.在所有满足1的子序列中取r-l最长的.

    分析:一个序列满足要求当且仅当min = gcd,关键的问题就是如何快速地求出min和gcd,最好是O(1),直接ST表就可以了.接下来二分枚举区间.一般这种求有多少个区间的都是先固定一个左端点然后二分右端点,但是这道题中min和gcd的单调性相同,不能直接这样二分,题目要求最大长度,那么直接二分长度,再枚举起点判断即可.

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 300010;
    int n, f[maxn][22], g[maxn][22], ans, anss[300010], tot, cnt, t[300010], anscnt;
    
    int gcd(int a, int b)
    {
        if (!b)
            return a;
        return gcd(b, a % b);
    }
    
    void init()
    {
        for (int j = 1; j <= 20; j++)
            for (int i = 1; i + (1 << j) - 1 <= n; i++)
            {
                f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
                g[i][j] = gcd(g[i][j - 1], g[i + (1 << (j - 1))][j - 1]);
            }
    }
    
    int geta(int l, int r)
    {
        int k = (int)((log(r - l + 1)) / log(2.0));
        return min(f[l][k], f[r - (1 << k) + 1][k]);
    }
    
    int getb(int l, int r)
    {
        int k = (int)((log(r - l + 1)) / log(2.0));
        return gcd(g[l][k], g[r - (1 << k) + 1][k]);
    }
    
    bool solve(int x)
    {
        cnt = 0;
        int tott = 0;
        memset(t, 0, sizeof(t));
        for (int i = 1; i + x <= n; i++)
            if (geta(i, i + x) == getb(i, i + x))
            {
                cnt++;
                t[++tott] = i;
            }
        if (cnt)
        {
            if (x > ans)
            {
                memcpy(anss, t, sizeof(t));
                tot = tott;
                anscnt = cnt;
            }
            return true;
        }
        return false;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &f[i][0]);
            g[i][0] = f[i][0];
        }
        init();
        int l = 0, r = n;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            if (solve(mid))
            {
                l = mid + 1;
                ans = mid;
            }
            else
                r = mid - 1;
        }
        if (ans != 0)
        {
            printf("%d %d
    ", anscnt, ans);
            for (int i = 1; i <= tot; i++)
                printf("%d ", anss[i]);
        }
        else
        {
            printf("%d %d
    ", n, ans);
            for (int i = 1; i <= n; i++)
                printf("%d ", i);
        }
    
        return 0;
    }

     

  • 相关阅读:
    如何导入文件夹在项目中
    KVC的学习
    ScrollView学习01
    KVO与KVC整理资料
    KVO监听者
    进程与线程
    解决SQL 2008数据库日志文件过大导致占满整个分区的问题:清理数据库日志文件
    SharePoint开发中发现的SharePoint本身的一些问题
    从十个方面提升SharePoint网站性能
    解决SharePoint2010文档库中新建文档不是保存到文档库而是保存到本地电脑的问题
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8011399.html
Copyright © 2020-2023  润新知