原题地址
题目大意:
给你一个长度为n的序列,求等差子序列的个数(不要求连续),1个数或2个数也算是等差子序列。
听说官方题解是
?
很明显一个
的题目然后计数。。。
我一开始想的是
的方法,,即
for(int i=1;i<=n;i++)
{
for(int k=1;k<=v;k++)
{
for(int j=1;j<i;j++) //转移
{
if(a[i]-a[j]==k) dp[i][k]+=dp[j][k]+1;
tot+=dp[j][k]+1;
}
}
}
然而
如何优化?
珂以发现,上面的代码是用公差枚举数,我们直接用数创造公差既珂,反正不会漏掉。
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
dp[i][a[i]-a[j]]+=dp[j][a[i]-a[j]]+1;
tot+=dp[j][a[i]-a[j]]+1;
}
}
和一些负下标的处理暂且不说,算法是正确的。
:
# include <bits/stdc++.h>
using namespace std;
int n;
const int N=1010,V=40005;
const int vik=20000;
const long long mod=998244353;
int dp[N][V];
int a[N];
void Input(void)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
return ;
}
void solve(void)
{
long long tot=0;
for(int i=1;i<=n;i++)
{
tot++;
for(int j=1;j<i;j++)
{
dp[i][a[i]-a[j]+vik]=(dp[i][a[i]-a[j]+vik]+dp[j][a[i]-a[j]+vik]+1)%mod;
tot=(tot+dp[j][a[i]-a[j]+vik]+1)%mod;
}
}
cout<<tot;
}
int main(void)
{
Input();
solve() ;
return 0;
}
内存500MB,所以开的下。