您的位置:首页 > 其它

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

2017-10-09 21:52 423 查看
题意:给n朵花上色,从m种颜色里面选择恰好k种颜色,求总数MOD 1e9+7

思路:首先如果用k种颜色给花上色的话,肯定是k∗(k−1)n−1种方案,但是要求的是恰好k种,很容易想到用容斥原理解决这个问题。 

设Ai表示没选第i种颜色的种类数目,则结果为

|A1¯¯¯¯∩A2¯¯¯¯∩...∩Ak¯¯¯¯| 
=k∗(k−1)n−1−∑|Ai|+∑|Ai∩Aj|+...+(−1)k∑|A1∩A2∩...∩Ak|

很容易计算

∑|Ai|=C1k∗(k−1)∗(k−2)n−1

同理

∑|Ai1∩Ai2∩...∩Aij|=Cjk∗(k−j)∗(k−j−1)n−1

所以要求的就是

|A1¯¯¯¯∩A2¯¯¯¯∩...∩Ak¯¯¯¯|∗Ckm

因为m≤1e9,k≤1e6这里面会用到一个组合数的技巧

Cim=Ci−1m∗m−i+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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  UVA