dp+树状数组优化。
dp[i][j]表示以a[i]结尾,最长上升序列长度为j的方案数。dp[i][j]=sum{dp[k][j-1]} 其中k<i&&a[k]<a[i]。 离散化后,可以用1000个树状数组维护。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi = acos(-1.0), eps = 1e-;
void File()
{
freopen("D:\\in.txt", "r", stdin);
freopen("D:\\out.txt", "w", stdout);
}
inline int read()
{
char c = getchar(); while (!isdigit(c)) c = getchar();
int x = ;
while (isdigit(c)) { x = x * + c - ''; c = getchar(); }
return x;
} int mod=;
const int maxn=;
int a[maxn],b[maxn],c[maxn][maxn],dp[maxn][maxn],ans;
int T,n,m; int lowbit(int x) { return x&(-x); }
int sum(int r,int p) { int res=; for(int i=p;i>;i=i-lowbit(i)) res=(res+c[r][i])%mod; return res; }
void update(int r,int p,int v) { for(int i=p;i<=;i=i+lowbit(i)) c[r][i]=(c[r][i]+v)%mod; } int main()
{
scanf("%d",&T); int cas=;
while(T--)
{
scanf("%d%d",&n,&m); memset(c,,sizeof c); ans=;
for(int i=;i<=n;i++) scanf("%d",&a[i]),b[i-]=a[i];
sort(b, b + n); int sz = unique(b, b + n) - b;
for(int i=;i<=n;i++) a[i]=lower_bound(b, b + sz, a[i])-b+;
for(int i=;i<=n;i++)
{
dp[i][]=; update(,a[i],dp[i][]);
for(int j=;j<=m;j++) { dp[i][j]=sum(j-,a[i]-); update(j,a[i],dp[i][j]); }
}
for(int i=;i<=n;i++) ans=(ans+dp[i][m])%mod;
printf("Case #%d: %d\n",cas++,ans);
}
return ;
}