Codeforces 395 D.Pair of Numbers

时间:2023-03-09 01:42:58
Codeforces 395 D.Pair of Numbers
D. Pair of Numbers
time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Simon has an array a1, a2, ..., an, consisting of n positive integers. Today Simon asked you to find a pair of integers l, r (1 ≤ l ≤ r ≤ n), such that the following conditions hold:

  1. there is integer j (l ≤ j ≤ r), such that all integers al, al + 1, ..., ar are divisible by aj;
  2. value r - l takes the maximum value among all pairs for which condition 1 is true;

Help Simon, find the required pair of numbers (l, r). If there are multiple required pairs find all of them.

Input

The first line contains integer n (1 ≤ n ≤ 3·105).

The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 106).

Output

Print two integers in the first line — the number of required pairs and the maximum value of r - l. On the following line print all l values from optimal pairs in increasing order.

Examples
input
5
4 6 9 3 6
output
1 3
2
input
5
1 3 5 7 9
output
1 4
1
input
5
2 3 5 7 11
output
5 0
1 2 3 4 5
Note

In the first sample the pair of numbers is right, as numbers 6, 9, 3 are divisible by 3.

In the second sample all numbers are divisible by number 1.

In the third sample all numbers are prime, so conditions 1 and 2 are true only for pairs of numbers (1, 1), (2, 2), (3, 3), (4, 4), (5, 5).

题目大意:给出长度为n的序列a[i],要求找到所有满足下列两个条件的子序列a[l],a[l+1],…,a[r]的个数: 
1.存在l<=j<=r,使得a[j]是a[l],a[l+1],…,a[r]的最大公因数 
2.在所有满足1的子序列中取r-l最长的.

分析:一个序列满足要求当且仅当min = gcd,关键的问题就是如何快速地求出min和gcd,最好是O(1),直接ST表就可以了.接下来二分枚举区间.一般这种求有多少个区间的都是先固定一个左端点然后二分右端点,但是这道题中min和gcd的单调性相同,不能直接这样二分,题目要求最大长度,那么直接二分长度,再枚举起点判断即可.

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ;
int n, f[maxn][], g[maxn][], ans, anss[], tot, cnt, t[], anscnt; int gcd(int a, int b)
{
if (!b)
return a;
return gcd(b, a % b);
} void init()
{
for (int j = ; j <= ; j++)
for (int i = ; i + ( << j) - <= n; i++)
{
f[i][j] = min(f[i][j - ], f[i + ( << (j - ))][j - ]);
g[i][j] = gcd(g[i][j - ], g[i + ( << (j - ))][j - ]);
}
} int geta(int l, int r)
{
int k = (int)((log(r - l + )) / log(2.0));
return min(f[l][k], f[r - ( << k) + ][k]);
} int getb(int l, int r)
{
int k = (int)((log(r - l + )) / log(2.0));
return gcd(g[l][k], g[r - ( << k) + ][k]);
} bool solve(int x)
{
cnt = ;
int tott = ;
memset(t, , sizeof(t));
for (int i = ; i + x <= n; i++)
if (geta(i, i + x) == getb(i, i + x))
{
cnt++;
t[++tott] = i;
}
if (cnt)
{
if (x > ans)
{
memcpy(anss, t, sizeof(t));
tot = tott;
anscnt = cnt;
}
return true;
}
return false;
} int main()
{
scanf("%d", &n);
for (int i = ; i <= n; i++)
{
scanf("%d", &f[i][]);
g[i][] = f[i][];
}
init();
int l = , r = n;
while (l <= r)
{
int mid = (l + r) >> ;
if (solve(mid))
{
l = mid + ;
ans = mid;
}
else
r = mid - ;
}
if (ans != )
{
printf("%d %d\n", anscnt, ans);
for (int i = ; i <= tot; i++)
printf("%d ", anss[i]);
}
else
{
printf("%d %d\n", n, ans);
for (int i = ; i <= n; i++)
printf("%d ", i);
} return ;
}