tyvj1114 等差数列

来源:互联网 发布:淘宝买洗衣机可靠吗 编辑:程序博客网 时间:2024/05/02 02:55

描述 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 [复制数据]

51 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;}








0 0