……

解题报告: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; 
}
posted @ 2020-05-12 10:06  童话镇里的星河  阅读(217)  评论(0编辑  收藏  举报