UVA - 1642 Magical GCD 数学
Magical GCD
The Magical GCD of a nonempty sequence of positive integers is defined as the product of its length
and the greatest common divisor of all its elements.
Given a sequence (a1, . . . , an), find the largest possible Magical GCD of its connected subsequence.
Input
The first line of input contains the number of test cases T. The descriptions of the test cases follow:
The description of each test case starts with a line containing a single integer n, 1 ≤ n ≤ 100000.
The next line contains the sequence a1, a2, . . . , an, 1 ≤ ai ≤ 1012
.
Output
For each test case output one line containing a single integer: the largest Magical GCD of a connected
subsequence of the input sequence.
Sample Input
1
5
30 60 20 20 20
Sample Output
80
题意:
给你N个数,求一个连续子序列,使得该序列中所有的最大公约数与序列长度的乘积最大
题解:
首先明确的做法是:枚举右端点,然后找到一个答案最大的左端点更新答案
那么如何找到这个最大的左端点,
假设我们求出了前i个数每个j(1<=j<=i) 的匹配的最优左端点,且gcd值,对应pos位置值已知,
那么我们可以根据gcd在非递增下,去更新这些gcd值和gcd值相同情况下 最左的左端点
这样的复杂度是nlogn的,
不同gcd至少相差2倍,我们就可以知道它是log的了
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N = 1e5+7, M = 30005, mod = 1e9+7, inf = 0x3f3f3f3f; typedef long long ll; //不同为1,相同为0 int T,n; ll a[N]; ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } vector<pair<ll,int > > v; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); v.clear(); ll ans = 0; for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int j=1;j<=n;j++) { v.push_back(make_pair(0,j)); int k = v.size(); for(int i=0;i<k;i++) { v[i].first = (gcd(v[i].first,a[j])); } sort(v.begin(),v.end()); vector<pair<ll,int > > now; for(int i=0;i<v.size();i++) { if(i == 0 || v[i-1].first != v[i].first) { now.push_back(v[i]); ans = max(ans, 1ll*v[i].first*(j - v[i].second+1)); } } v = now; } cout<<ans<<endl; } return 0; }