播放列表【容斥定理】

版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/84975144

小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;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/84975144