HDU 5400 Arithmetic Sequence(2015 Multi-University Training Contest 9 2015多校联合)

Arithmetic Sequence

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


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
 
题目传送门: HDU 5400

这道题目其实很简单。用一个循环就可以做。不过开始想的有点复杂了。题目的意思就是给你一个序列,并且给你两个数字,d1和d2。让你从序列中找有多少个区间符合条件,条件是存在一个i使得1<=j<i,满足aj+1=aj+d1,并且i<=j<n,满足aj+1=aj+d2。也就是说存在一个断点,使得断点前的序列公差为d1,断点后的序列公差为d2。
需要注意的是,存在特殊情况,每个数字本身都是一种情况,也就是a0。
还有就是,存在公差全部为d1或者全部为d2的。
但是不存在先d2后d1的情况。所以,我们要找的就是,先出现d1后出现d2。只要找到第一个出现d2之后的不是d2的情况,然后把断点加到这里就可以了。
拿题目里给的例子来说,拿第一个例子来讲,
0 2 0 -2 0
它们的差值是 2 -2 -2 2 找到第一个出现在-2之后的2,也就是第四个数字。所以说前三个数字就是一种排列情况。2 -2 -2。一共有几种情况?就是3+2+1=6。
具体来说就是(2),(-2),(-2),(2,-2),(-2,-2),(2,-2,-2)。所以只要找到断点之后,把前面累加的情况再递减累加然后加到ans中就可以了。
然后再从断点处继续向下计算下一种序列情况就可以了。

代码:
#include <cstdio>
#include <iostream>
#define N 100010
int a[N];
int c[N];
using namespace std;
int main()
{
	int n,d1,d2;
	int flag;     //用来标记出现的是d1还是d2
	long long ans,sum;
	while(~scanf("%d%d%d",&n,&d1,&d2))
	{
		flag=0;
		ans=0;
		sum=0;
		scanf("%d",&a[0]);
		for(int i=1;i<n;i++)
		{
			scanf("%d",&a[i]);
			c[i-1]=a[i]-a[i-1];
		}
		for(int i=0;i<n-1;i++)
		{
			if(flag==0)
			{
				if(c[i]==d1)
					sum++;
				else if(c[i]==d2)
				{
					flag=1;
					sum++;
					continue;
				}
				else
				{
					while(sum)
					{
						ans+=sum;
						sum--;
					}
					sum=0;
				}
			}
			if(flag==1)
			{
				if(c[i]==d2)
					sum++;
				else
				{
					while(sum)
					{
						ans+=sum;
						sum--;
					}
					sum=0;
					flag=0;
					i--;
				}
			}
		}
		while(sum)
		{
			ans+=sum;
			sum--;
		}
		printf("%lld\n",ans+n);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值