1. 程式人生 > >Codeforces 8VC Venture Cup 2016 - Elimination Round F. Group Projects 差分DP*****

Codeforces 8VC Venture Cup 2016 - Elimination Round F. Group Projects 差分DP*****

div c++ cat have font pie sca allow mda

F. Group Projects

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 imbalance of 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 ≤ 200, 0 ≤ 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
3 2
2 4 5
output
3

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.

題意:

  給n個人, 讓我們分成若幹組, 每組的價值是最大值減去最小值,所有組價值之和不能超過k

  求方案數

題解:

  這個是一道很強的DP

  我們用dp[i][j][k]表示考慮了前i個數了, 有j個組是開放的(所謂開放指的是只有最小值, 還沒有最大值, 還可以進人), 當前值之和為k 的方案數。

  我們先排序, 這樣, 對於開放的組, 每次的累加量就都是 j*(a[i] - a[i-1])。

  那麽轉移的情況要考慮這麽幾個:

  1. 第i個數單組一組

  2.第i個數新開一組, 作為新組的最小值

  3.第i個數關閉一組, 作為這個組的最大值。

  4.第i個數進入j個組中的某一組。

  提示,要理解差分思想

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 200+10, M = 1e3+20,inf = 2e9,mod = 1e9+7;


LL dp[2][N][M];
int n,m,a[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    dp[0][0][0] = 1;
    a[0] = a[1];
    int now = 0;
    for(int i = 1; i <= n; ++i) {
        now ^= 1;
        memset(dp[now],0,sizeof(dp[now]));
        for(int j = 0; j <= i; ++j) {
            for(int k = 0; k <= m; ++k) {
                if(dp[now^1][j][k] == 0) continue;


                if(j*(a[i]-a[i-1])+k > m) break;

                dp[now][j][j*(a[i]-a[i-1])+k] += dp[now^1][j][k],dp[now][j][j*(a[i]-a[i-1])+k] %= mod;
                dp[now][j+1][j*(a[i]-a[i-1])+k] += dp[now^1][j][k],dp[now][j+1][j*(a[i]-a[i-1])+k] %= mod;

                if(j)dp[now][j-1][k+j*(a[i]-a[i-1])] += 1LL*j*dp[now^1][j][k],dp[now][j-1][k+j*(a[i]-a[i-1])]%=mod;

                dp[now][j][k+j*(a[i]-a[i-1])] += 1LL*j*dp[now^1][j][k],dp[now][j][k+j*(a[i]-a[i-1])] %= mod;

            }
        }
    }
    LL ans = 0;
    for(int i = 0; i <= m; ++i) {
        ans = (ans + dp[now][0][i])%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

Codeforces 8VC Venture Cup 2016 - Elimination Round F. Group Projects 差分DP*****