图片说明
思路:分组背包,f[i][j]:前i组选择价值为j的方案数。
图片说明

#include <bits/stdc++.h>
#define LL long long
using namespace std;

int a[105][105];
LL f[105][10005];
int main(){
    int n, k, m; scanf("%d%d", &n, &k);
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i][0]);
        for(int j=1; j<=a[i][0]; j++){
            scanf("%d", &a[i][j]);
        }
    }
    f[0][0]=1;
    for(int i=1; i<=n; i++){
        for(int s=0; s<=10000; s++){
            if(f[i-1][s]){
                for(int j=1; j<=a[i][0]; j++){
                    f[i][s+a[i][j]]+=f[i-1][s];
                }
            }
        }
    }
    LL ans=0;
    for(int i=1; i<=10000; i++){
        if(f[n][i]<k){
            ans+=f[n][i]*i;
            k-=f[n][i];
        }
        else{
            ans+=k*i;
            k=0;
            break;
        }
    }
    cout<<ans<<endl;

    return 0;
}

图片说明
思路:翻译一下就是:求长度为M的LIS数量。
图片说明

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int mod=1e9+7;

struct BitTree
{
    LL c[100005];
    int lowbit(int p){
        return (p&-p);
    }
    void Add(int x, LL v)
    {
        if (!x)
            return;
        while (x < 100005)
            c[x] = (c[x]+v)%mod, x += lowbit(x);
    }
    LL Ask(int x)
    {
        LL t = 0;
        while (x)
            t += c[x], t%=mod, x -= lowbit(x);
        return t;
    }

}bit[51];

int a[100005], b[100005];
int main(){
    int n, m; scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
        b[i]=a[i];
    }
    sort(b+1, b+n+1);
    int cnt=unique(b+1, b+n+1)-b-1;
    for(int i=1; i<=n; i++){
        a[i]=lower_bound(b+1, b+cnt+1, a[i])-b;
    }
    for(int i=1; i<=n; i++){
        for(int len=1; len<=m; len++){
            if(len==1){
                bit[1].Add(a[i], 1);
            }
            else{
                bit[len].Add(a[i], bit[len-1].Ask(a[i]-1));
            }
        }
    }
    printf("%lld\n", bit[m].Ask(100004));

    return 0;
}