码迷,mamicode.com
首页 > 其他好文 > 详细

【bzoj4052】[Cerc2013]Magical GCD 暴力

时间:2017-08-24 19:42:41      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:size   max   mic   using   sam   string   zoj   fine   bsp   

题目描述

给出一个长度在 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\n" , ans);
	}
	return 0;
}

 

 

【bzoj4052】[Cerc2013]Magical GCD 暴力

标签:size   max   mic   using   sam   string   zoj   fine   bsp   

原文地址:http://www.cnblogs.com/GXZlegend/p/7424150.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!