Hdu 5400 Arithmetic Sequence 数学推理

Arithmetic Sequence

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


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+d1  and 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
 

Author
xudyh
 

Source

 
给你长度为n的序列,求有多少个连续的子序列满足前一半公差d1,后一半公差d2.
 
先求出连续的公差d1、d2的序列长度。然后讨论:
1.子序列长度为1,共n个符合要求的序列。
2.子序列公差为d1或d2,设长度为len,共有len*(len+1)/2个子序列符合要求。
3.公差d1、d2的序列连在一起,我们在前一段选一个头,后一段选一个尾。设长度分别为lena、lenb,
共有lena*lenb种答案。
 
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=1000005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L); 
ll a[maxn],lena[maxn],lenb[maxn];

int main() {
int n,i;
        ll d1,d2;
    while (scanf("%d%lld%lld%lld",&n,&d1,&d2,&a[1])!=EOF) {
        mem0(lena);mem0(lenb);
        for (i=2;i<=n;i++) {
            scanf("%lld",&a[i]);
            if (a[i]-a[i-1]==d1) lena[i]=lena[i-1]+1; else 
                if (a[i]-a[i-1]==d2) lenb[i]=lenb[i-1]+1;
        }
        ll ans=n,last=-1;
        lena[n+1]=lenb[n+1]=0;
        for (i=2;i<=n+1;i++) {
            if (lena[i-1]!=0&&lena[i]==0) {
                ans+=lena[i-1]*(lena[i-1]+1)/2;
                last=i-1;
            } else if (lenb[i-1]!=0&&lenb[i]==0) {
                if (last==i-1-lenb[i-1]) ans+=lena[last]*lenb[i-1];
                ans+=lenb[i-1]*(lenb[i-1]+1)/2;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值