HDU_4045 Machine scheduling 數學

http://acm.hdu.edu.cn/showproblem.php?pid=4045

題意 :

有N臺機器,要從中選出r臺來,這r臺機器之間必須要滿足兩兩之間的編號不小於k,選出r臺機器之後,要把這r臺機器分成不超過m組,問共有多少中滿足條件的種數。

思路:

這是一個組合數學計數的問題,我們可以將原問題分成兩個子問題來解決: Q1:從n個數中選出r個數,要求兩兩之間的編號差不小於k;Q2:將r個數分成不超過m組,共有多少種方法。Q2可以用第二類Strling數來求解,我們只需要先打出Strling數的表,那麼ans2 = S[r][1] + S[r][2] + S[r][3] + ... + S[r][ m ] ,這裏需要注意的是第二類Strling數的分組是不能有空盒的分組,並且球之間是有區別的。 接着我們來解決Q1,我們可以這樣來想,我們把n臺機器看作完全相同的n臺,那麼我們可以先選出r臺機器來,將他們排成一排,爲了確保兩兩之間的編號不小於k,那麼我們在任意兩臺機器之間插入k-1臺機器,這樣我們就剩下a ( n - r - (r-1) * (k-1) )臺機器了,這a臺機器可以插入到上面的 r 臺機器之間的任意位置,並且前後也可以插入, 這樣我們就相當於是要求下面方程的解的組數:x1 + x2 + ... xr+1 = a

每個xi都可以爲0 ,因爲可以爲0 , 我們就不能用簡單的隔板法來求了,因爲隔板法是要求每個xi都>=1的,我們可以先將每個xi加1,然後再用隔板法就可以了。最後ans1 = C[a + r][r] , 那麼最後的答案就是ans1 * ans2 了。 


代碼:

#include <stdio.h>
#include <string.h>
typedef __int64 LL ;
const LL Mod = 1000000007 ;
const int MAXN = 1010 ;
LL n ,r , k , m ;
LL S[MAXN][MAXN] ;
LL C[MAXN][MAXN] ;

void init(){
    S[1][1] = 1 ;
    for(int i=2;i<MAXN ;i++){
        S[i][1] = S[i][i] = 1 ;
        for(int j=2;j<i;j++){
            S[i][j] = ( S[i-1][j-1] + ( j*S[i-1][j] % Mod )  ) % Mod;
        }
    }
    C[0][0] = C[1][0] = C[1][1] = 1 ;
    for(int i=2;i<MAXN;i++){
        C[i][0] = 1 ;
        for(int j=1;j<=i;j++){
            C[i][j] = C[i-1][j-1] ;
            if( j<=i-1 )
                C[i][j] = ( C[i][j] + C[i-1][j] ) % Mod ;
        }
    }
}

LL solve(){
    if( n<r+(r-1)*(k-1) )    return 0 ;
    LL ans1 = C[ n-(r-1)*(k-1) ][r] ;
    LL ans2 = 0 ;
    for(int j=1;j<=m;j++){
        ans2 = ( ans2 + S[r][j] ) % Mod ;
    }
    return  ( ans1 * ans2 ) % Mod ;
}

int main(){
    init() ;
    while( scanf("%I64d%I64d%I64d%I64d",&n,&r,&k,&m) == 4){
        printf("%I64d\n",solve() );
    }
    return 0 ;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章