1. 程式人生 > >播放列表【容斥定理】

播放列表【容斥定理】

小Hi的手機中存著N首他喜愛的歌曲。現在小Hi希望製作一個長度為L的播放列表,滿足

1. 每一首歌至少播放一編

2. 同一首歌不能連續播放,之間至少間隔一首其他歌曲

請你計算一共有多少種不同的播放列表滿足條件?由於結果可能非常大,你只需要輸出結果模1000000009的餘數。

Input

兩個整數N和L。

對於30%的資料,1 ≤ N ≤ 5,N ≤ L ≤ 10  

對於100%的資料,1 ≤ N ≤ 1000, N ≤ L ≤ 2000

Output

一個整數,代表答案。

Sample Input

3 4

Sample Output

18

  一開始看成了1e9+7交了次罰時……

  一道容斥的模板題吧,有N個喜歡的歌,還有L長度的選擇,那麼我們每次考慮的是選取這麼多的歌,然後會發現,有"abc"三種歌的時候,會選擇到"aba"這樣的情況,那麼顯然是不行的,那麼我們就要把選擇三種的可能中的只用了兩種的刪除掉,但是,刪完兩種,還要再考慮到只剩一種的情況是不是刪多了,所以,還要加上去,這樣一直處理到N為1時候就可以跳出了,並且,此時就是答案。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1005;
const int mod = 1e9 + 9;
int N, L;
ll jiecheng[maxN];
void pre_did()
{
    jiecheng[0] = jiecheng[1] = 1;
    for(int i=2; i<maxN; i++) jiecheng[i] = jiecheng[i-1] * (ll)i%mod;
}
ll fast_mi(ll x, ll y)
{
    ll ans = 1;
    while(y)
    {
        if(y & 1) ans = ans * x %mod;
        x = x * x % mod;
        y>>=1;
    }
    return ans;
}
ll Cal(ll down, ll up) { return jiecheng[down] * fast_mi(jiecheng[up], mod-2) %mod * fast_mi(jiecheng[down - up], mod - 2) %mod; }
int main()
{
    pre_did();
    while(scanf("%d%d", &N, &L)!=EOF)
    {
        ll ans = 0;
        for(int i=0; i<N; i++)
        {
            ans = ( ans + ( ((i&1)==0)?1:(-1)) * Cal(N, N-i) * (N-i) %mod * fast_mi(N-i-1, L-1)%mod + mod )%mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}