令xi=sum和为i,且不包含>=i的数的集合的数量
则numi=A[1...n]中等于i的数个数=Bi−xi
于是,m为背包大小,numi为物品个数,每个物品体积=i,dpj=体积为j时方案数,求背包即可
又因为∑numi<=50,所以复杂度为O(n∗m)
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<queue>
//#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int N = 1e4 +5;
ll b[N];
ll x[N];
int num[N];
void printAns(int n,int m){
int cnt=0;
for(int i=0;i<=m;++i){
for(int j=0;j<num[i];++j){
++cnt;
printf("%d%c",i,cnt==n?'\n':' ');
}
}
}
void dp(int m){
fill(x,x+m+1,0);
x[0]=1;
for(int i=1;i<=m;++i){
num[i]=b[i]-x[i];
for(int j=1;j<=num[i];++j){
for(int k=m;k>=i;--k){
x[k]+=x[k-i];
}
}
}
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<=m;++i){
scanf("%lld",&b[i]);
}
dp(m);
printAns(n,m);
}
return 0;
}