这道题利用一种类似离散化的思想。
用f[i][j]表示以 i 结尾公差为 j 的等差数列个数。
不必枚举出所有的公差,更新的是该数与前面的所有数的公差方案数+1。
对于两个数字,他们组成的等差数列的公差一定是一样的。
那么我们不必去枚举公差,直接枚举第 i 个数前面那个数,得到公差进行转移即可。
以 i 结尾且上一个数是 j 的公差为 k 的等差数列数量是以 j 结尾公差为 k 的等差数列数加一。
转移的过程中直接计数,顺便把数字数为一的区间加上。
注意第二维数组开二倍将负数右移即可。
这样只需要n方的转移就可以了。
AC代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int p=2e4+200,N=1e3+10,M=4e4+400,mod=998244353;
int a[N],f[N][M];
int read(){int x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;};
void write(int x){if(x<0){putchar('-');x=-x;}if(x>9)write(x/10);putchar(x%10+'0');return;}
signed main(){
int n=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
int ans=0;
for(int i=1;i<=n;i++){
ans++;
for(int j=i-1;j>=1;j--){
f[i][a[i]-a[j]+p]+=f[j][a[i]-a[j]+p]+1;
f[i][a[i]-a[j]+p]%=mod;
ans+=f[j][a[i]-a[j]+p]+1;
ans%=mod;
}
}
write(ans);
return 0;
}