题目大意:给你一个序列,求子序列为等差数列的子序列个数。序列长度$n<=2000$,最高的塔高$v<=20000$。
这种计数类的题,大概就是dp的套路了⑧。开始设计的是一个错误的状态:设$f[i][j]$为到前$i$个塔选了$j$个的方案数,但是我们再看一看就会发现这是错的,因为等差数列啊,我们并没有考虑公差鸭。所以我们再设计一个状态:设$f[i][j]$表示到第$i$个塔为止,公差为$j$的方案数。开始想的是$O(n^3)$算法 ,还要枚举公差,但是后来发现不需要特意枚举公差,只要枚举一个数的之前的数,直接用他们的公差即可。复杂度$O(n^2)$。
因为公差可能有负数,所以我们再加上一个大数即可。
开始不加快读竟然会T一个点,加了就A了??? 我佛了233.
Code
#include<cstdio> #include<algorithm> #define maxn 1090 using namespace std; typedef long long ll; const ll moder=998244353; int n,fake=20000; int h[maxn]; ll ans,f[maxn][40009]; void re(int &x) { x=0; char ch=getchar(); bool flag=false; while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); x=flag ? -x : x; } int main() { re(n); for(int i=1;i<=n;i++) re(h[i]); for(int i=1;i<=n;i++) for(int j=1;j<i;j++) { (f[i][h[i]-h[j]+fake]+=f[j][h[i]-h[j]+fake]+1)%=moder; (ans+=f[j][h[i]-h[j]+fake]+1)%=moder; } (ans+=n)%=moder; printf("%lld ",ans); return 0; }