tyvj1114 等差数列

4 篇文章 0 订阅

描述 Description
等差数列的定义是一个数列S,它满足了(S[i]-S[i-1]) = d (i>1)。显然的一个单独的数字或者两个数字也可以形成一个等差数列。
经过一定的学习小C发现这个问题太简单了,等差数列的和不就是(Sn+S1)*n/2?因为这个问题实在是太简单了,小C不屑于去解决它。这让小C的老师愤怒了,他就找了另外一个问题来问他。
小C的老师给了他一个长度为N的数字序列,每个位置有一个整数,他需要小C帮他找到这个数字序列里面有多少个等差数列。
……
这个问题似乎太难了,小C需要你的程序帮他来解决这个问题。

输入格式 InputFormat
第一行一个整数N,表示老师给出的数字序列的长度。
第二行有N个整数A[i],表示数字序列每个数字的大小。


输出格式 OutputFormat
输出只有一行一个整数,表示这个序列中的等差数列的个数(mod 9901)。
样例输入 SampleInput [复制数据]
5
1 4 2 3 7


样例输出 SampleOutput [复制数据]
17
数据范围和注释 Hint
对于30%的数据,N <= 100
对于70%的数据,N <= 500
对于100%的数据,N <= 1000;-500 <= A[i] <= 500

等差数列肯定有公差,还有数的个数,根据学长得出dp[i][j]表示以第i个数结尾的公差为j的数列个数

那么状态转移公式为:dp[i][j] += dp[k][j] + 1; (k=1--i-1)

解释一下:假设前k个组成的数列个数为sum=dp[k][j], 那么在添加num[i]后,数列个数自然+1,

那么我们就枚举num[i]与前面所有的差值,即为公差.

最后因为一个数也算数列,所以要最终的和+n,要把所有差值()的可能性都列举出来,得到最终的和,

具体看代码,这里要注意差值可能为负的,所以对j要有限制,因为差值最小为-1000,所以要对j+1000.


代码:

#include <stdio.h>
#include <string.h>

long long dp[1002][2002];

int num[1002];
int main()
{
	int n;
	scanf("%d", &n);

	memset(dp, 0, sizeof(dp));	//初值为0 
	for (int i=1; i<=n; ++i)
	{
		scanf("%d", &num[i]);
	}
	int cha;

	for (int i=2; i<=n; ++i)
	{
		for (int j=1; j<=i-1; ++j)
		{
			cha = num[i]-num[j] + 1000; // 当前和前面某个差值
			dp[i][cha] += dp[j][cha]+1; // 前面j个组成的数列,添加num[i],组成新的数列,所以要+1
		}
	}
	long long sum = n; // 每一个数都是等差数列
	for (int j=1; j<=n; ++j)
	for (int i=0; i<=2000; ++i)
	{
		sum += dp[j][i];
		sum %= 9901;
	}
	printf("%lld\n", sum);
	return 0;
}








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值