[LUOGU] 4933 大师

\(Orz\) \(ljt12138!\)
设状态\(f[i][j]\)表示以\(i\)为结尾,公差为\(j\)的长度大于\(1\)的数列有几个。
然后转移方程就很好想了。
\(k=H[i]-H[j]\)
\(f[i][k]=\sum\limits_{j=1}^{i-1} (f[j][k]+1)\)
之前的等差数列加上最后那个数形成新的等差数列,再加上\((i,j)\)
每次枚举到一个\(f[j][k]\)就把答案加上这个数,表示这个数列后面续接上\(i\)的贡献,但是这样的话长度为1和2的序列就需要单独计算了。
(希望没有出锅,欢迎拍砖)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=1005,base=20000,mod=998244353;
int f[1005][40005],n,h[N],ans;
inline void add(int &x,int y) {
	if(x+y>=mod) return x=x+y-mod,void();
	x=x+y;
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&h[i]);
	for(int i=1;i<=n;i++) {
		add(ans,i);//len=1 or 2
		for(int j=1;j<i;j++) {
			int tp=h[i]-h[j];
			add(ans,f[j][tp+base]);
			add(f[i][tp+base],f[j][tp+base]+1);
		}
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2018-10-22 15:03  SWHsz  阅读(125)  评论(0编辑  收藏  举报