解题报告:luogu P4933
题目链接:P4933 大师
一道不怎么套路的 \(dp\),所以就没做出来/kk/dk。
我们记 \(dp[i][j]\) 为以 \(i\) 为首项,\(j\) 为公差的等差数列个数。
考虑倒推。
当 \(l,r\) 的差为 \(k\)时,容易知道:
\[dp[l][k]=dp[r][k]+1
\]
为啥?
情况一:在原来的等差数列前加一个数;
情况二:构造一个长为 \(2\) 的等差数列,两项分别为 \(l,r\)。
最后答案的统计。
只要出现一个,就加上。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define read(x) scanf("%d",&x)
#define MAXN 200005
#define MOD 998244353
int n,h[1005];
int dp[1005][MAXN<<1];
int ans=0;
int main()
{
read(n);
for(int i=1;i<=n;i++) read(h[i]);
for(int i=n-1;i>=1;i--)
{
for(int j=i+1;j<=n;j++)
{
dp[i][h[j]-h[i]+MAXN]=(dp[i][h[j]-h[i]+MAXN]+dp[j][h[j]-h[i]+MAXN]+1)%MOD;
ans=(ans+dp[j][h[j]-h[i]+MAXN]+1)%MOD;
}
}
printf("%d\n",(ans+n)%MOD);
return 0;
}