UVA 1642 Magical GCD (思路+哈希map)

来源:互联网 发布:c语言如何输出汉字 编辑:程序博客网 时间:2024/06/01 07:17

大体题意:

给你n 个整数(n <= 1e5)要求选择一个连续的子序列,使得gcd * 长度 最大?

思路:

按照刘汝佳分析做的,加入一个数后,给它的所有后缀的gcd 打一个表,gcd 相同的 保留长度大的,其余的全部删除。

那么这个表中元素数量最大是log2 j 个,很小的一个数。

因此随便做了,但是不能用有序的stl  如set 还是会超时。

用两个Hash map 来会导就可以了。

#include <cstdio>#include <cstring>#include <algorithm>#include <set>#include <vector>#include <unordered_map>#define Max(a,b) ((a)>(b)?(a):(b))#define ps push_back#define fi first#define se second#define Siz(x) (int)x.size()using namespace std;typedef long long LL;const int maxn = 1e5 + 10;LL gcd(LL a,LL b){    return !b ? a : gcd(b,a%b);}LL a[maxn];LL b[maxn];unordered_map <LL,int>mp,mp2;unordered_map<LL,int>::iterator it;int T, n;int main(){    scanf("%d",&T);    while(T--){        LL ans = 0;        mp.clear();        scanf("%d",&n);        for (int i = 1; i <= n; ++i){            scanf("%lld",a+i);            ans = Max(ans,a[i]);        }        mp[a[1] ] = 1;        for (int i = 2; i <= n; ++i){            int cnt = 0;            mp2.clear();            for (it = mp.begin(); it != mp.end();++it){                LL ng = gcd(it->fi, a[i]);                LL nlen = it->se + 1;                if (!mp2.count(ng)){                    mp2[ng] = nlen;                    ans = Max(ans,nlen*ng);                }                else {                    if (mp2[ng] < nlen){                        mp2[ng] = nlen;                        ans = Max(ans,nlen*ng);                    }                    else ans = Max(ans,mp2[ng]*ng);                }            }            if (!mp2.count(a[i]))mp2[a[i] ] = 1;            mp = mp2;        }        printf("%lld\n",ans);    }    return 0;}/**2530 60 20 20 2042 2 3 4ans = 80**/


0 0