小米oj 有多少個等差數列(動態規劃)
阿新 • • 發佈:2018-11-01
有多少個等差數列?
序號:#20難度:困難時間限制:500ms記憶體限制:10M
描述
等差數列是常見數列的一種,如果一個數列從第二項起,每一項與它的前一項的差等於同一個常數,這個數列就叫做等差數列,而這個常數叫做等差數列的公差,公差常用字母d表示。即對於數列S,它滿足了(S[i]-S[i-1]) = d (i \gt 1)(S[i]−S[i−1])=d(i>1)。 顯然,一個數字無法構成等差數列,而任意兩個數字可以形成一個等差數列。 這裡給出了一個長度為N (0 \lt N \lt 200)N(0<N<200)的數字序列,每個位置有一個整數(-100 \le \text{整數} \le 100)(−100≤整數≤100),需要找到這個數字序列裡包含多少個等差數列,序列順序固定,無需排序。 輸入資料格式:\text{S[0] S[1] S[2] ... S[N]}S[0] S[1] S[2] ... S[N](以半形空格符分隔,N \gt 1N>1) 輸出資料格式:等差數列數量 MM; 其中數列 SS 的項為整數
請注意時間複雜度的限制。
輸入
輸入一個數列[ 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
思路:設dp[i][k]表示以a[i]為起點,k為公差的等差數列的個數。
轉移方程為:if(a[j]+k==a[i])dp[j][k]+=(dp[i][k]+1); (j<i)
#include<bits/stdc++.h> #include<stdio.h> #include<iostream> #include<cmath> #include<math.h> #include<queue> #include<set> #include<map> #include<iomanip> #include<algorithm> #include<stack> using namespace std; #define inf 0x3f3f3f3f typedef long long ll; char buf[100000]; int a[205]; ll dp[205][405]; int main() { #ifndef ONLINE_JUDGE //freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE while(gets(buf)) { memset(dp,0,sizeof(dp)); int v; int n=0; char *p=strtok(buf," "); while(p) { sscanf(p,"%d",&v); a[n++]=v; p=strtok(NULL," "); } ll ans=0; for(int k=-200;k<=200;k++) { for(int i=n-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<n;i++) { for(int k=0;k<=400;k++) { ans+=dp[i][k]; } } cout<<ans<<endl; } return 0; }