Rikka with Subset

题解:

如果 Bi​​ 是 B 数组中除了 B0​​ 以外第一个值不为 00的位置,那么显然 ii 就是 AA 中的最小数。

现在需要求出删掉 i后的B数组,过程大概是反向的背包,即从小到大让 b[j]-=b[j-i]。(类似筛法的思想) (这里顺序推过去的时候,我们把j-i看做一个组,当i要消去之后,对j的影响,不就是j-i存在的次数么

(当然和为(j-i)的情况要把包含i的情况处理掉不然会有重复计算,顺推就好了))。

时间复杂度 O(nm)

注意对0这个点特殊处理一下。

比赛的时候想到实现不了,再次抱大佬大腿。。。

ac代码:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll a[60];
ll b[10001];
int n,m;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%d %d",&n,&m);
        for(int i=0;i<=m;i++) scanf("%lld",&b[i]);
        int cnt=0;
        b[0]--;
        int flag=0;
        while(1)
        {
            ll i;
            flag=0;
            for(i=0;i<=m;i++)
            {
                if( b[i] > 0)
                {
                   // cout<<i<<' '<<endl;
                    if(i==0)
                    {
                        for(int j=0;j<b[i];j++) a[cnt++]=0;
                    }
                    else a[cnt++]=i;
                    if( i!=0 ) b[i]--;
                    break;
                }
            }
            if(i==0)
            {
                for(ll j=1;j<=m;j++)
                {
                    if(b[j] >= b[0]) b[j] -= b[0];
                }
                b[0]=0;
               // for(ll j=1;j<=m;j++) cout<<b[j]<<' ';
               // cout<<endl;
            }
            else for(ll j=i;j<=m;j++) b[j] -= b[j-i];
            if(cnt==n) break;
        }
        cout<<a[0];
        for(int i=1;i<n;i++) printf(" %lld",a[i]);
        cout<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/z1141000271/p/7308841.html