题意是给你n个数让你求选出m个数且单调递增的个数;
首先给出的数值特别大 而数的个数才1000 所以先离散处理下 ;
具体思路: dp+树状数组;
我是建了m棵树 用来记录没j个的情况 dp【i】【j】表示以j结尾的数 里面递增数为i个 求这些书里面包含num【j】的情况 这样跑i 建树
初始化dp【1】【j】 = 1;
for(i = 2; i <= m; i++) { memset(sum, 0, sizeof(sum)); for(j = 1; j <= n; j++) { dp[i][j] = (dp[i][j] + find(num[j].value - 1)) % mod; update(num[j].value, dp[i - 1][j]); } }至于建树和求和按照正常来就行
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; const int Max = 1010; const int mod = 1e9 + 7; struct node { int value; int ii; }num[Max]; __int64 sum[Max]; __int64 dp[Max][Max]; int cmp(node a, node b) { return a.value < b.value; } int cmp1(node a, node b) { return a.ii < b.ii; } int update(int a, __int64 c) { for(int i = a; i <= 1000; i += (i&(-i))) sum[i] = (sum[i] + c) % mod; return 0; } __int64 find(int a) { __int64 s = 0; for(int i = a; i >= 1; i -= i&(-i)) s = (s + sum[i]) % mod; return s; } int main() { int T, i, j, n, m, d = 1; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); for(i = 1; i <= n ; i++) { scanf("%d", &num[i].value); num[i].ii = i; } sort(num + 1, num + 1 + n, cmp); int k = -1; int x = 0; for(i = 1; i <= n; i++) { if(num[i].value != k) { k = num[i].value; num[i].value = ++x; } else { num[i].value = x; } } sort(num + 1, num + 1 + n, cmp1); memset(dp, 0, sizeof(dp)); for(i = 1; i <= n; i++) dp[1][i] = 1; for(i = 2; i <= m; i++) { memset(sum, 0, sizeof(sum)); for(j = i-1; j <= n; j++) { dp[i][j] = (dp[i][j] + find(num[j].value - 1)) % mod; update(num[j].value, dp[i - 1][j]); } } __int64 ans = 0; for(i = 1; i<= n; i++) ans = (ans + dp[m][i]) % mod; printf("Case #%d: ", d++); printf("%I64d\n", ans); } return 0; }