HDU6092(动态规划思想)

来源:互联网 发布:电脑监控软件破解 编辑:程序博客网 时间:2024/05/21 07:13

其实咱们都做过给你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 longusing 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;}


原创粉丝点击