题意:给你N朵花,M种颜料(n,m<=1e9),要求给所有花染色,且相邻的花不能用同样的颜色,求出最后恰好用了k种
颜料的方案数(k<=1e5)
题解:当我们用至少k中染色的时候 f[k] = k*(k-1)^(n-1) 其中包括了 至少k-1中的,我们需要减去C(k,k-1)*f[k-1] ,但是很明显我们多减了一次至少f[k-2]次的,举个栗子:假设有1 2 3 4 5,我们先减去1 3 4 5 在减 2 3 4 5 所以其中多减了一次 3 4 5的 所以要再加上y一次f[k-2] 以此类推 ,这就是一个容斥,但是n,k,很大我们怎么办的,C(n,m+1)=C(n,m)*(n-m)/(m+1) 因此我们就需要求逆元了
注意乘法运算啊,每次乘,都要取模,否则就超1e9了 坑
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e6+100;
const ll mod=1000000007;
ll C[N],inv[N],n,m,k;
ll ksm(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
void init()
{
for(int i=1;i<N;i++)
inv[i]=ksm(i,mod-2);
}
void cal(ll x)
{
C[0]=1;
for(int i=1;i<=k;i++)
C[i]=((C[i-1]*(x-i+1)%mod)*inv[i]%mod)%mod;
}
int main()
{
init();
int T,nn=1;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld",&n,&m,&k);
cal(k);
ll ans=k*ksm(k-1,n-1)%mod;
for(ll i=2;i<=k-1;i++)
{
if((k-i)%2) ans=(ans-C[i]*(i*ksm(i-1,n-1)%mod)%mod)%mod;
else ans=(ans+C[i]*(i*ksm(i-1,n-1)%mod)%mod)%mod;
}
cal(m);
printf("Case #%d: %lld\n",nn++,(C[k]*ans%mod+mod)%mod);
}
return 0;
}