Description
小H是个善于思考的学生,现在她又在思考一个有关序列的问题。
她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。
这个特殊区间满足,存在一个k(L <= k <= R),并且对于任意的i(L <= i <= R),ai都能被ak整除。这样的一个特殊区间 [L, R]价值为R - L。
小H想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些区间又分别是哪些呢?你能帮助她吧。
Input
第一行,一个整数n.
第二行,n个整数,代表ai.
Output
第一行两个整数,num和val,表示价值最大的特殊区间的个数以及最大价值。
第二行num个整数,按升序输出每个价值最大的特殊区间的L.
Sample Input
输入1:
5
4 6 9 3 6
输入2:
5
2 3 5 7 11
Sample Output
输出1:
1 3
2
输出2:
5 0
1 2 3 4 5
Data Constraint
30%: 1 <= n <= 30 , 1 <= ai <= 32.
60%: 1 <= n <= 3000 , 1 <= ai <= 1024.
80%: 1 <= n <= 300000 , 1 <= ai <= 1048576.
100%: 1 <= n <= 500000 , 1 <= ai < 2 ^ 31.
.
.
.
.
.
分析
水法真神奇,暴力出奇迹!
数据太水了,自己出的数据都能把程序卡到80分,结果交上去就AC了
我们暴力枚举每一位为k
以当前位置向左、向右扩展,遇到不合法的就停止
最后判断并统计答案即可
注意,可能会出现长度一样,所在区间也一样,这时就要判重(例如有多个数字为1的情况)
(但这种情况未得到有效的验证,有可能只有1这种情况)
最后要将答案的数组排序输出(以免出现数组不为有序的情况,同时,这种情况未得到有效的验证)
所以你爱打不打
而真正的正解是这样的:
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long ansl[500010],ansr[500010],a[500010];
int n;
inline long long read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int main()
{
n=read();
for (int i=1;i<=n;i++)
a[i]=read();
int num=0,val=0;
for (int i=1;i<=n;i++)
{
int l=i,r=i;
while (a[r+1]%a[i]==0&&r<n) r++;
while (a[l-1]%a[i]==0&&l>1) l--;
if (r-l>val)
{
val=r-l;
num=0;
num++;
ansl[num]=l;
ansr[num]=r;
} else
if (r-l==val)
{
if (ansl[num]!=l||ansr[num]!=r)
{
num++;
ansl[num]=l;
ansr[num]=r;
}
}
}
sort(ansl+1,ansl+num+1);
printf("%d %d
",num,val);
for (int i=1;i<=num;i++)
printf("%lld ",ansl[i]);
return 0;
}