zoukankan      html  css  js  c++  java
  • UVa 1642

    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4517

    题意:

    输入一个n(n≤100000)个元素的正整数序列,求一个连续子序列,使得该序列中所有元素的最大公约数与序列长度的乘积最大。
    例如,5个元素的序列30, 60, 20, 20, 20的最优解为{60, 20, 20, 20},乘积为gcd(60,20,20,20)*4=80。

    分析:

    从左到右枚举序列的右边界j,然后快速求出左边界i≤j,使得MGCD(i,j)最大。
    其中MGCD(i,j)定义为gcd(a[i],a[i+1],...,a[j])*(j-i+1)。
    考虑序列5, 8, 6, 2, 6, 8,当j=5时需要比较i=1, 2, 3, 4, 5时的MGCD(i,j),如下表所示:

    i=1,gcd表达式=gcd(5,8,6,2,6),gcd值=1,序列长度=5。
    i=2,gcd表达式=gcd(8,6,2,6),gcd值=2,序列长度=4。
    i=3,gcd表达式=gcd(6,2,6),gcd值=2,序列长度=3。
    i=4,gcd表达式=gcd(2,6),gcd值=2,序列长度=2。
    i=5,gcd表达式=gcd(6),gcd值=6,序列长度=1。

    从下往上看,gcd表达式里每次多一个元素,有时gcd不变,有时会变小,而且每次变小时一定是变成了它的某个约数。
    换句话说,不同的gcd值最多只有logj种!当gcd值相同时,序列长度越大越好,所以可以把表简化一下:

    gcd值=1,i=1。
    gcd值=2,i=2。
    gcd值=6,i=5。

    因为表里只有logj个元素,所以可以依次比较每一个i对应的MGCD(i,j),时间复杂度为O(logj)。
    下面考虑j从5变成6时,这个表会发生怎样的变化。
    首先,上述所有gcd值都要再和a6=8取gcd,然后要加入i=6的项目,gcd值为8。
    由于相同的gcd值只需要保留i的最小值,所以i=5被删除,最终得到如下表所示结果。

    gcd值=1,i=1。
    gcd值=2,i=2。
    gcd值=8,i=6。

    总时间复杂度为O(nlogn)。

    代码:

     1 #include <cstdio>
     2 #include <vector>
     3 using namespace std;
     4 
     5 typedef long long int LLI;
     6 struct Item {
     7     LLI g;
     8     int p;
     9 };
    10 
    11 LLI gcd(LLI a, LLI b) {
    12     return b == 0 ? a : gcd(b, a%b);
    13 }
    14 
    15 int main() {
    16     int T, n;
    17     LLI v, ans;
    18     scanf("%d", &T);
    19     while(T--) {
    20         ans = 0;
    21         vector<Item> vec;
    22         scanf("%d", &n);
    23         for(int t = 0; t < n; t++) {
    24             scanf("%lld", &v);
    25             for(int i = 0; i < vec.size(); i++) vec[i].g = gcd(vec[i].g, v);
    26             vec.push_back((Item){v,t});
    27             vector<Item> nvec;
    28             for(int i = 0; i < vec.size(); i++) {
    29                 if(i != 0 && vec[i].g == vec[i-1].g) continue;
    30                 ans = max(ans, vec[i].g * (t-vec[i].p+1));
    31                 nvec.push_back(vec[i]);
    32             }
    33             vec = nvec;
    34         }
    35         printf("%lld
    ", ans);
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    2019牛客暑期多校训练营(第三场)- LRU management
    2019牛客暑期多校训练营(第三场)- F Planting Trees
    HDU1392 Surround the Trees
    2019 Multi-University Training Contest 2
    3101 阶乘分解 (数学)
    Prime Distance POJ
    反素数ant HYSBZ
    B. Nirvana Codeforces Round #549 (Div. 2) (递归dfs)
    C. Queen Codeforces Round #549 (Div. 2) (搜索)
    Cow Relays POJ
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9733816.html
Copyright © 2011-2022 走看看