题目描述
等差数列 指从第二项起,每一项与它的前一项的差等于同一个常数的一种数列,且这个常数叫做等差数列的公差
例如:数列 15913 就是一个公差为4的等差数列。
现给定一个长度为 n 的序列 a1,a2,….,an,
请问该序列中,有多少个长度不小于 3 的子段满足等差数列?
输入格式
输入共两行
第一行,一个正整数 n,表示给定序列长度
第二行,n 个整数,分别表示序列的每一项 a1,a2,…, an
输出格式
输出一个整数,表示满足条件的子段个数。
数据范围
。对于 30% 的数据,1<n< 100
。对于 60% 的数据,1<n< 104
。对于 100% 的数据,1<n< 105,-10°< a < 109
样例数据
输入:
10
-1 1 3 3 3 2 3 2 1 0
输出:
5
说明:
区间[1,3],[3,5],[7,10],[7,9],[8,10]均满足等差数列要求
分析
知识点:组合数学,贪心,数学
解题思路:
考虑每次找最长的一段使公差 ppp 相等,设这一段的长度为 lenlenlen ,那么这一段的区间数为len×(len−1)2\frac{len \times (len-1)}{2}2len×(len−1) 再减去所有长为 2 的区间数 len−1len-1len−1 即得合法方案数
考虑 p 不等的时候 ,新等比数列只能从 i-1 位置开始
复杂度 O(n)O(n)O(n)
代码
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int const N=1e5+10;
LL n,m,ans,a[N];
int main(){
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
int l=1,p=a[2]-a[1];
for(int i=3;i<=n;i++){
if(a[i]-a[i-1]!=p){
LL len=i-l;
if(len*(len-1)>=6) ans+=len*(len-1)/2-len+1;
l=i-1; p=a[i]-a[i-1];
}
}
LL len=n-l+1;
if(len*(len-1)>=6) ans+=len*(len-1)/2-len+1;
printf("%lld",ans);
}
304

被折叠的 条评论
为什么被折叠?



