思路:
首先不难想出最暴力的做法,三重循环的DP,直接炸开
考虑怎么优化
只有当a[k]<a[i]的时候才会进行累加,那不就是一个类似于逆序对的做法吗?
然后直接用树状数组统计就行了
c o d e code code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long T, t, tot;
long long n, m;
long long a[100010], f[2010][2010], q[20010];
long long p=1e9+7;
long long c[2010][2010];
void lsh()
{
for(long long i=1; i<=n; i++)
q[i]=a[i];
sort(q+1, q+1+n);
tot=unique(q+1, q+1+n)-1-q;
for(long long i=1; i<=n; i++)
a[i]=lower_bound(q+1, q+1+tot, a[i])-q;
}
long long lowbit(long long x)
{return x & -x;}
void add(long long i, long long x, long long y)
{
for(; x<=tot; x+=lowbit(x))
(c[i][x]+=y)%p;
}
long long sum(long long i, long long x)
{
long long ans=0;
for(; x; x-=lowbit(x))
(ans+=c[i][x])%p;
return ans;
}
int main()
{
scanf("%lld", &T);
while(T--)
{
t++;
scanf("%lld%lld", &n, &m);
for(long long i=1; i<=n; i++)
scanf("%lld", &a[i]);
lsh();
for(long long i=1; i<=n; i++)
{
for(long long j=1; j<=m; j++)
{
if(j==1)
f[i][j]=1;
else
f[i][j]=sum(j-1, a[i]-1)%p;
add(j, a[i], f[i][j]);
}
}
long long ans=0;
for(long long i=m; i<=n; i++)
ans=(ans+f[i][m])%p;
printf("Case #%lld: %lld\n", t, ans);
memset(f, 0, sizeof(f));
memset(c, 0, sizeof(c));
}
return 0;
}