CF626F:Group Projects

F. Group Projects
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n students in a class working on group projects. The students will divide into groups (some students may be in groups alone), work on their independent pieces, and then discuss the results together. It takes the i-th student ai minutes to finish his/her independent piece.

If students work at different paces, it can be frustrating for the faster students and stressful for the slower ones. In particular, the imbalanceof a group is defined as the maximum ai in the group minus the minimum ai in the group. Note that a group containing a single student has an imbalance of 0. How many ways are there for the students to divide into groups so that the total imbalance of all groups is at most k?

Two divisions are considered distinct if there exists a pair of students who work in the same group in one division but different groups in the other.

Input

The first line contains two space-separated integers n and k (1 ≤ n ≤ 2000 ≤ k ≤ 1000) — the number of students and the maximum total imbalance allowed, respectively.

The second line contains n space-separated integers ai (1 ≤ ai ≤ 500) — the time it takes the i-th student to complete his/her independent piece of work.

Output

Print a single integer, the number of ways the students can form groups. As the answer may be large, print its value modulo 109 + 7.

Examples
input
Copy
3 2
2 4 5
output
Copy
3
input
Copy
4 3
7 8 9 10
output
Copy
13
input
Copy
4 0
5 10 20 21
output
Copy
1
Note

In the first sample, we have three options:

  • The first and second students form a group, and the third student forms a group. Total imbalance is 2 + 0 = 2.
  • The first student forms a group, and the second and third students form a group. Total imbalance is 0 + 1 = 1.
  • All three students form their own groups. Total imbalance is 0.

In the third sample, the total imbalance must be 0, so each student must work individually.

题解:

非常妙的一道DP题

显然,每个集合中的关键在于其最大值与最小值

定义一个开放的集合为一个只有最小值而没有最大值(即暂时未加入其最大值)的集合,将序列排序后,从小到大依次加入每个a[i],那么一个集合的代价,可视为闭合前每个(a[i+1]-a[i])的累加(因为对于每个开放的集合,即使你不加入当前的a[i],后续也必定会加入另一些更大的元素来闭合它,所以可以把最终的代价拆分为多段,每段加一些,将本应最后计算的代加在每次转移过程中动态更新)

令f[i][j][k]表示添加了前i个数时,还有j个开放的集合,当前总代价和为k的方案数,那么对于当前所有开放的集合,每次转移的总累加量为j*(a[i+1]-a[i]),而转移则有4种:

1.将a[i]加入一个开放的集合,不闭合

2.将a[i]加入一个开放的集合并闭合它

3.用a[i]新开一个集合,不闭合

4.用a[i]新开一个集合并闭合它

另外,本题要用滚动数组,否则会爆空间

#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
int n,k,ans=0;
int s[205],f[2][205][1005];
int main()
{
    memset(f,0,sizeof(f));
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&s[i]);
    sort(s+1,s+1+n);
    int p1=0,p2=1;
    f[p1][1][0]=1;
    f[p1][0][0]=1;
    for(int i=1;i<=n-1;i++)
        {
        for(int j=0;j<=i;j++)
            for(int t=0;t<=k;t++)
                {
                    if(f[p1][j][t]==0)
                       continue;  
                    int dt=s[i+1]-s[i],val=f[p1][j][t];
                    f[p1][j][t]=0;
                    if(t+j*dt>k)
                       continue;
                    f[p2][j][t+j*dt]=((f[p2][j][t+j*dt]%MOD)+((long long)j*val%MOD))%MOD;
                    if(j-1>=0)
                       f[p2][j-1][t+j*dt]=((f[p2][j-1][t+j*dt]%MOD)+((long long)j*val%MOD))%MOD;
                    f[p2][j+1][t+j*dt]=(f[p2][j+1][t+j*dt]%MOD+val%MOD)%MOD;
                    f[p2][j][t+j*dt]=(f[p2][j][t+j*dt]%MOD+val%MOD)%MOD;   
                }
            swap(p1,p2);   
        }
    for(int i=0;i<=k;i++)
        ans=(ans%MOD+f[p1][0][i]%MOD)%MOD;
    printf("%d",ans);                
    return 0;            
}
View Code

 

转载于:https://www.cnblogs.com/nanjolno/p/9344696.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值