题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4991
题目的意思是求长度为 m 的上升序列有多少个;
设DP[I][J]表示 以第i个元素结尾的 长度为j的序列的个数
dp[i][j]=sum(dp[k][j-1]) (i>k &&a[i]>a[k])
数字有1万个,先离散化一下,把所有数字对应到1到n之间,然后用数组数组进行求和就好
代码如下:
#include <iostream> #include <cmath> #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; const int N = 10010; const int mod = 123456789; typedef long long LL; LL c[N],a[N],b[N]; int n,m; LL dp[N][104]; int lowbit(int x) { return x & (-x); } void update(int pos,LL val) { while(pos <= n) { c[pos] += val; pos += lowbit(pos); } } LL query(int pos) { LL res = 0; while(pos > 0) { res = (res+c[pos])%mod; pos -= lowbit(pos); } return res; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); b[i] = a[i]; } sort(b+1,b+n+1); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) dp[i][1] = 1; for(int j=2;j<=m;j++) { memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { int ind = lower_bound(b+1,b+n+1,a[i])-b; dp[i][j] = query(ind-1); update(ind,dp[i][j-1]); } } LL ans = 0; for(int i=1;i<=n;i++) ans = (ans + dp[i][m])%mod; printf("%I64d\n",ans); } return 0; }