其实咱们都做过给你k个数然后求这k个数有多少个子集的和等于k的题
那么现在就是反过来了
那么做法也是很神奇的
对于序列a,我的1的个数就是a[1]的个数
那么如果我去掉所有的1,并且维护a序列的性质不变,那么2的个数就是a[2]
那么问题来了,如何去掉所有的数k后维护a的性质不变呢
解决方法就是我们一个一个的去掉k
现在我去掉一个k后
由于我知道1-k-1的数全部都被去掉了
那么a[k+1]-a[2*k-1]是没有影响的,因为只有比k大的数是无法组成这些数的
接下来,a[i]=a[i]-a[i-k]
为什么呢,因为a[i-k]已经是去掉k的a序列了,然后对于k,只有i-k +k才能成为i所以减去a[i-k]即维护了a序列的性质
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 100100
#define ll long long
using namespace std;
ll a[maxn],b[maxn];
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
ll m,n;
scanf("%lld %lld",&m,&n);
for (ll k=0;k<=n;k++)
scanf("%lld",&a[k]);
ll nn(0);
for (ll k=1;k<=n;)
{
if (nn>=m) break;
nn++;
while(a[k]==0)
k++;
b[nn]=k;a[k]--;
for (ll j=k+k;j<=n;j++)
a[j]=a[j]-a[j-k];
}
printf("%lld",b[1]);
for (ll k=2;k<=nn;k++)
printf(" %lld",b[k]);
printf("\n");
}
return 0;
}