小米OJ-20-有多少个等差数列?

描述

等差数列是常见数列的一种,如果一个数列从第二项起,每一项与它的前一项的差等于同一个常数,这个数列就叫做等差数列,而这个常数叫做等差数列的公差,公差常用字母d表示。即对于数列S,它满足了(S[i]-S[i-1]) = d。 显然,一个数字无法构成等差数列,而任意两个数字可以形成一个等差数列。 这里给出了一个长度为N(0

请注意时间复杂度的限制。

输入

输入一个数列[ 2 7 4 5 6 ],该数列包含等差数列: [ 2 7 ] [ 2 4 ] [ 2 5 ] [ 2 6 ] [ 7 4 ] [ 7 5 ] [ 7 6 ] [ 4 5 ] [ 4 6 ] [ 5 6 ] [ 2 4 6 ] [ 4 5 6 ]

输出

上例共包含12组等差数列,故应输出12

输入样例

2 7 4 5 6
3 3 3 3

输出样例

12
11


解析:这是一道动态规划的算法。初步分析递推关系可以得出任何一个n>2的等差数列都是由n-1的等差数列得来的。那么如何用二维数组去区分每个不同的等差数列呢?我们提取每个等差数列的起点以及公差,用dp[i][k]表示起点为a[i],公差为k的这一类等差数列,dp[i][k]的值为这类等差数列的个数。然后从后往前遍历,得到这样一个转移方程if(a[j]+k==a[i])dp[j][k]+=(dp[i][k]+1); (j
#include
using namespace std;

int main()
{
    //存放数字序列,数列长度小于200
    int a[201];
    //存放等差数列及其个数,共公差范围为-200~200,这里要做一些转化
    int dp[201][401];
    string input;
    while(getline(cin,input))
    {
        stringstream ss(input);
        int item;
        //数列个数和等差数列总数
        int num = 0;
        int ans = 0;
        while(ss>>item)
        {
            a[num] = item;
            num++;
        }
        memset(dp,0,sizeof(dp));
        for(int k = -200; k <= 200 ; k++)
        {
            for(int i = num-1 ; i > 0 ; i--)
            {
                for(int j = i-1 ; j >= 0 ; j--)
                {
                    if(a[j] + k == a[i])
                    {
                        dp[j][k+200] += dp[i][k+200] + 1;
                    }
                }
            }
        }
        for(int i = 0; i < num; i++)
        {
            for(int k = 0 ; k <= 400 ; k++)
            {
                ans += dp[i][k];
            }
        }
        cout<

这一题对数列长度以及整数的范围都给出了条件,所以可以多利用这些条件,用内存空间来换取算法时间上的性能!!!

你可能感兴趣的:(小米OJ-20-有多少个等差数列?)