随笔 - 531  文章 - 0  评论 - 3  阅读 - 10215 

给定一个长度为n 的序列 , 求 它有多少个长度为 m的严格递增子序列。

 

 f[i][j] += f[i-1][k] (a[k]<a[i], k<i )

 

 优化 : 维护前缀和,根据a[k]<a[i]  ,以a[ ] 为下标维护树状数组 , add(a[i] ,f[i-1][j] )

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std ;
 const int N =1e3+4;
 const int mod =1e9+7;
 #define int long long
int n,m,a[N],f[N][N];
int tr[N];
int bin[N],len;
 
int lowbit(int x){
    return x&-x;
}
void add(int x, int v){
    for(; x <= len; x += lowbit(x))
        tr[x] = (tr[x]+v),tr[x]%=mod;
}
int qry(int x){
    int  t=0;
    for(;x;x-=lowbit(x)) t+=tr[x],t%=mod;
    return t;
}
void solve(int cas){
        int i,j;
        for(j=2; j<=m;j++) {
            for(i=1;i<=len;i++) tr[i] = 0;
            for(i=1;i<=n;i++){
                f[i][j] =qry(a[i] - 1);
                add(a[i], f[i][j-1]);
            }
        }
        int ans=0;
    for(int i=1;i<=n;i++) ans+=f[i][m],ans%=mod;
   printf("Case #%d: %lld\n",cas,ans);
}
 
signed main(){
    int tes,cas=0;
    cin>>tes;
    while(tes--){
        len=0;
        cin>>n>>m;
        for(int i = 1; i <= n; i++){
           cin>>a[i];
            bin[i] = a[i];
            f[i][1]=1;
        }
        sort(bin+1, bin+1+n);
        len = unique(bin+1, bin+1+n)-(bin+1);
        for(int i = 1; i <= n; i++)
        a[i] = lower_bound(bin+1, bin+1+len, a[i]) -bin;
         
        solve(++cas);
   }   
}

 

posted on   towboat  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示