数字对 (长乐一中模拟赛day2T2)

时间:2021-08-12 01:53:40

2.数字对

【题目描述】

小H是个善于思考的学生,现在她又在思考一个有关序列的问题。

她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。

这个特殊区间满足,存在一个k(L <= k <= R),并且对于任意的i(L <= i <= R),ai都能被ak整除。这样的一个特殊区间 [L, R]价值为R - L。

小H想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些区间又分别是哪些呢?你能帮助她吧。

【输入格式】

第一行,一个整数n.

第二行,n个整数,代表ai.

【输出格式】

第一行两个整数,num和val,表示价值最大的特殊区间的个数以及最大价值。

第二行num个整数,按升序输出每个价值最大的特殊区间的L.

【样例输入1】

5

4 6 9 3 6

【样例输出1】

1 3

2

【样例输入2】

5

2 3 5 7 11

【样例输出2】

5 0

1 2 3 4 5

【数据范围】

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.

思路:

  暴力出奇迹,乱搞压正解!

  我们暴力枚举每个ak点

  然后记录最长的区间

  判一下重

  轻松ac

来,上代码:

#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; int n,if_Z,ai[],head_num=; char word; vector<int>ans[]; inline void read_int(int &now_001)
{
now_001=,if_Z=;word=getchar();
while(word<''||word>'')
{
if(word=='-') if_Z=-;
word=getchar();
}
while(word<=''&&word>='')
{
now_001=now_001*+(int)(word-'');
word=getchar();
}
now_001*=if_Z;
} int main()
{
ios::sync_with_stdio(false);
read_int(n);
for(int i=;i<=n;i++) read_int(ai[i]);
int lik,rik,cur_1,maxn=;
for(int i=;i<=n;i++)
{
lik=i,rik=i,cur_1=;
while(lik->)
{
if(ai[lik-]%ai[i]==) lik--;
else break;
}
while(rik+<=n)
{
if(ai[rik+]%ai[i]==) rik++;
else break;
}
ans[rik-lik].push_back(lik);
maxn=max(maxn,rik-lik);
}
sort(ans[maxn].begin(),ans[maxn].end());
vector<int>::iterator it=ans[maxn].begin();
while(it<ans[maxn].end())
{
if(*it!=ai[head_num])
{
head_num++;
ai[head_num]=*it;
}
it++;
}
printf("%d %d\n",head_num,maxn);
for(int i=;i<=head_num;i++) printf("%d ",ai[i]);
return ;
}