• 【bzoj4052】[Cerc2013]Magical GCD 暴力


    题目描述

    给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12。 
    求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大。

    样例输入

    1
    5
    30 60 20 20 20

    样例输出

    80


    题解

    暴力

    由于$gcd$具有结合律,所以如果$gcd(a,b)$比$a$小,那么至少小了一半。

    所以所有以一个数为右端点的区间中,本质不同的$gcd$个数只有$log a$个。

    于是从左向右枚举右端点,统计出以该点为右端点的所有$gcd$以及区间长度,统计答案;在端点移动时与所有前一个点的$gcd$再取一个$gcd$,然后去重即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100010
    using namespace std;
    typedef long long ll;
    ll a[N] , pos[N] , val[N];
    int tot;
    ll gcd(ll a , ll b)
    {
    	return b ? gcd(b , a % b) : a;
    }
    int main()
    {
    	int T;
    	scanf("%d" , &T);
    	while(T -- )
    	{
    		tot = 0;
    		int n , i , j , last;
    		ll t , ans = 0;
    		scanf("%d" , &n);
    		for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &a[i]);
    		for(i = 1 ; i <= n ; i ++ )
    		{
    			last = tot , tot = 0;
    			for(j = 1 ; j <= last ; j ++ )
    			{
    				t = gcd(val[j] , a[i]);
    				if(t != val[tot]) pos[++tot] = pos[j] , val[tot] = t , ans = max(ans , t * (i - pos[j] + 1));
    			}
    			if(a[i] != val[tot]) pos[++tot] = i , val[tot] = a[i] , ans = max(ans , a[i]);
    		}
    		printf("%lld
    " , ans);
    	}
    	return 0;
    }
    

     

  • 相关阅读:
    npropress进度条插件的使用
    让img图片像背景一样显示
    vue-cli3配置多页面入口
    7中漂亮的纯css字体
    速查手册
    推荐系统架构
    leetcode 172. 阶乘后的零
    C++ string和int互相转换
    特征分解
    线性代数基础
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7424150.html
Copyright © 2020-2023  润新知