UVA1642 : 마법 GCD
질문의 의미 :
길이 주어 \ (N- \ 당량. 5 ^ 10 \) , 각 번호 \ (A_I \ leq10 12 ^ {} \) , 연속적인 시퀀스를 찾는되도록 최대 시퀀스 규칙의 길이 제품.
\ (T \) 데이터의 집합.
아이디어 :
간격 최대 공약수 템플릿 제목입니다.
열거 \ ((I, J) \ ) 폭력, 그 시간 복잡도는 \ (O (N- 형 ^ 2logn) \) , 윌 확실히 초과.
주어 시퀀스 \ (A \) , 연속하는 서브 세그먼트 \ (GCD \) 가 \ (로그 (최대 \ {A_I \}) \) 수있다.
\ (GCD (1, ..., I) = 최대 공약수 (GCD (1, ..., I-1)와, (I)) \) .
때마다 그래서 고정 소수점 오른쪽 다른 찾기 위해 왼쪽에 \ (GCD \) 값을.
#include<bits/stdc++.h>
#define PLI pair<long long, int>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
ll a[maxn];
int n;
ll gcd(ll a, ll b)
{
if(b == 0) return a;
return gcd(b, a%b);
}
//fir->gcd sec->右端点索引
vector<PLI> g[maxn];
void solve()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
g[i].clear();
}
for(int i = 1; i <= n; i++)
{
ll x = a[i], y = i;
g[i].push_back({x,y});
for(int j = 0; j < g[i-1].size(); j++)
{
PLI p = g[i-1][j];
ll t = gcd(x, p.first);
if(t != x)
{
x = t; y = p.second;
g[i].push_back({x, y});
}
}
}
ll ans = 0;
for(int i = 1; i <= n; i++)
{
PLI p1, p2;
for(int j = 0; j < g[i].size()-1; j++)
{
p1 = g[i][j];
p2 = g[i][j+1];
ans = max(ans, p1.first*(i-p2.second));
}
p1 = g[i][g[i].size()-1];
ans = max(ans, (ll)(i)*p1.first);
}
cout << ans << endl;
}
int main()
{
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}