思路:分组背包,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; }