hdoj 5400 Arithmetic Sequence 【构造等差数列】

探讨了如何解决一种特殊的等差数列问题,即在给定序列中寻找所有符合特定条件的子序列,该问题涉及到算法设计和数据结构应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



Arithmetic Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1173    Accepted Submission(s): 511


Problem Description
A sequence b1,b2,,bn are called (d1,d2)-arithmetic sequence if and only if there exist i(1in) such that for every j(1j<i),bj+1=bj+d1and for every j(ij<n),bj+1=bj+d2.

Teacher Mai has a sequence a1,a2,,an. He wants to know how many intervals [l,r](1lrn) there are that al,al+1,,ar are (d1,d2)-arithmetic sequence.
 

Input
There are multiple test cases.

For each test case, the first line contains three numbers n,d1,d2(1n105,|d1|,|d2|1000), the next line contains n integers a1,a2,,an(|ai|109).
 

Output
For each test case, print the answer.
 

Sample Input
5 2 -2 0 2 0 -2 0 5 2 3 2 3 3 3 3
 

Sample Output
12 5
 



定义N个数组成的序列b1、b2、b3、...、bn为(d1, d2)序列

满足:存在一个i 使得 b[j+1] = b[j] + d1(1<=j<i) && b[j] = b[j-1] + d2(i<=j<=N).


题意:给你一个N个数组成的序列,问你里面有多少个(d1, d2)序列。



以前看过这道题,没敢写。。。


思路:构造两个等差数列。

定义数组l[i]——为从左到右且以a[i]元素为末尾的等差数列的长度

定义数组r[i]——为从右到左且以a[i]元素为末尾的等差数列的长度


如图:


我们单独考虑把位置3作为i所拥有的区间数目,其中l[3] = 2,r[3] = 2。

一、d1 != d2

区间组合[1, 3] + [3, 4]、[3, 5]中任一个,区间组合[2, 3] + [3, 4]、[3, 5] 共计l[3] * r[3] = 4;

二、d1 != d2 —— 序列1到5是满足题意的等差数列

区间组合[3, 4]和[3, 5]共r[i] = 2个。

(i为2时,算过了[2, 3]。同理统计在位置2为i时,我们只能选择右边的区间,因为i为1时,算过了[1, 2])



AC代码:


#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define MAXN 100000+10
using namespace std;
LL l[MAXN], r[MAXN];
int a[MAXN];
int main()
{
    int N, d1, d2;
    while(scanf("%d%d%d", &N, &d1, &d2) != EOF)
    {
        for(int i = 1; i <= N; i++)
            scanf("%d", &a[i]);
        l[1] = 1;//初始只有1
        for(int i = 2; i <= N; i++)
        {
            if(a[i] == a[i-1] + d1)
                l[i] = l[i-1] + 1;
            else
                l[i] = 1;
        }
        r[N] = 1;//初始只有1
        for(int i = N-1; i >= 1; i--)
        {
            if(a[i] == a[i+1] - d2)
                r[i] = r[i+1] + 1;
            else
                r[i] = 1;
        }
        LL ans = 0;
        if(d1 != d2)
        {
            for(int i = 1; i <= N; i++)
                ans += l[i] * r[i];
        }
        else
        {
            for(int i = 1; i <= N; i++)
                ans += r[i];
        }
        printf("%lld\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值