Loading

Magical GCD

Magical GCD

CERC 2013。

思路

维护区间GCD考虑ST表维护。考虑对于固定左端点开始的序列,它的GCD是单调不增的,那么对于固定的一个GCD值,序列长度越长积自然越大,因此考虑枚举左端点,查找对于它的每个GCD的最大\(F\),二分查找GCD的右边界。由于需要遍历所有点作为左端点,每次的GCD的值最多有\(\log\)个,加上二分右边界,因此复杂度为\(O(n\log^2 n)\)

代码

inline int GCD(int l,int r)
{
	int len = log2(r - l + 1);
	return __gcd(gcd[l][len],gcd[r - (1 << len) + 1][len]);
}

inline int find(int i,int l,int r,int val)
{
	int res;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(GCD(i,mid) == val) res = mid,l = mid + 1;
		else r = mid - 1;
	}
	return res;
}

signed main()
{
	T = read();
	while(T--)
	{
		n = read();
		for(int i = 1;i <= n;i++) gcd[i][0] = a[i] = read();
		for(int k = 1;k <= 17;k++){
			for(int i = 1;i + (1 << k) - 1 <= n;i++){
				gcd[i][k] = __gcd(gcd[i][k - 1],gcd[i + (1 << (k - 1))][k - 1]);
			}
		}
		ans = 0;
		for(int i = 1;i <= n;i++){
			for(int l = i,r = 0;l <= n;l = r + 1){
				r = find(i,l,n,GCD(i,l));
				ans = max(ans,(r - i + 1) * GCD(i,r));
			}
		}
		write(ans),putchar('\n');
	}
	return 0;
}
posted @ 2021-10-03 08:40  场-room  阅读(27)  评论(0)    收藏  举报