UVAlive7040(组合数,容斥原理,逆元)

来源:互联网 发布:文明网络标语 编辑:程序博客网 时间:2024/05/17 04:47

题意:给n朵花上色,从m种颜色里面选择恰好k种颜色,求总数MOD 1e9+7

思路:首先如果用k种颜色给花上色的话,肯定是k(k1)n1种方案,但是要求的是恰好k种,很容易想到用容斥原理解决这个问题。 
Ai表示没选第i种颜色的种类数目,则结果为

|A1¯¯¯¯A2¯¯¯¯...Ak¯¯¯¯| 
=k(k1)n1|Ai|+|AiAj|+...+(1)k|A1A2...Ak|

很容易计算

|Ai|=C1k(k1)(k2)n1

同理

|Ai1Ai2...Aij|=Cjk(kj)(kj1)n1

所以要求的就是

|A1¯¯¯¯A2¯¯¯¯...Ak¯¯¯¯|Ckm

因为m1e9,k1e6这里面会用到一个组合数的技巧

Cim=Ci1mmi+1i

AC code

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MOD = 1e9+7;const int MAXN = 1e6+10;LL inv[MAXN],Cm[MAXN],Ck[MAXN];int n,m,k;LL _pow(LL a,int n){    if(n==0) return 1;    LL sum=_pow(a,n/2);    sum=sum*sum%MOD;    if(n&1) sum=sum*a%MOD;    return sum;}void inverse(){    inv[1]=1;    for(int i=2;i<MAXN;i++)        inv[i]=_pow(i,MOD-2);}void C(){    Ck[0]=Cm[0]=1;    for(int i=1;i<=k;i++)    {        Cm[i]=Cm[i-1]%MOD*(m-i+1)%MOD*inv[i]%MOD;        Ck[i]=Ck[i-1]%MOD*(k-i+1)%MOD*inv[i]%MOD;    }}int main(){    int t;scanf("%d",&t);    inverse();    for(int tt=1;tt<=t;tt++)    {        scanf("%d%d%d",&n,&m,&k);        int sgn=1;        LL sum=0;        C();        for(int i=k;i>=1;i--)        {            sum=(sum+Ck[i]*i%MOD*_pow(i-1,n-1)*sgn%MOD+MOD)%MOD;            sgn=-sgn;        }        sum=(sum*Cm[k])%MOD;        printf("Case #%d: %lld\n",tt,sum);    }    return 0;}






阅读全文
1 0