UVA 7040

大意:有一排一共n个珠子,要用m种颜色中的恰好k种去涂色,相邻的两个颜色要不同,问方案数。

做法大概就是C(m,k)表示m中k种颜色,然后对于每k个颜色进行容斥(大概就是这样)

代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <string.h>
#include <cstdio>
#include <map>
#include <queue>
#include <math.h>
#include <cstring>
#include <set>
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const double eps=1e-9;
const LL MAXN=1000000+23;
LL quick(LL x,LL a)
{
    LL res=1;
    while(a)
    {
        if(a&1)res=res*x%MOD;
        a>>=1;
        x=x*x%MOD;
    }
    return res%MOD;
}


LL n,m,k;
LL jk[1000000+23],jm[1000000+23],jk1[1000000+23],nk[1000000+23];
LL C(LL a,LL b)
{
    if(a==b||b==0)return 1;
    LL r=nk[b];
    return r*jm[b]%MOD;
}

LL C1(LL a,LL b)
{
    if(a==b||b==0)return 1;
    LL r=nk[b];
    return r*jk1[b]%MOD;
}
int main()
{
    jk[0]=1;

    for(int i=1;i<=1000000+3;i++)
    {
        jk[i]=jk[i-1]*i;
        jk[i]%=MOD;//k的阶乘
        nk[i]=quick(jk[i],MOD-2);//阶乘对应的逆元
    }
    int T;
    int cas=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&n,&m,&k);
        jm[0]=1;jk1[0]=1;

        for(int i=1;i<=k;i++)
        {
            jk1[i]=jk1[i-1]*(k-i+1);
            jk1[i]%=MOD;//k*(k-1)*...*(k-i+1)
            jm[i]=jm[i-1]*(m-i+1);
            jm[i]%=MOD;//m*(m-1)*...*(m-i-1),用来求组合数的
        }
        //printf("%lld %lld\n" ,C(6,4),C(6,3));
        //printf("***%lld\n",jk1[2]);
        LL ans=k*quick(k-1,n-1)%MOD;//最多用k种进行涂色,注意是最多,不是恰好
        //printf("ans=%lld\n",ans);
        int s=-1;
        for(int i=k-1;i>=2;i--)//对k容斥
        {
            LL res=C1(k,i)*i%MOD*quick(i-1,n-1);
            res%=MOD;
            //else res=C1(k,i)*i*quick(i-1,n-1);
            //printf("res=%lld\n",res);
            ans+=res*s;
            s*=-1;
            ans%=MOD;
        }
        ans=ans*C(m,k)%MOD;
        //printf("C=%lld\n",C(m,k));
        printf("Case #%d: %lld\n",++cas,(ans%MOD+MOD)%MOD);
    }
    return 0;
}

额(⊙o⊙)…...大概就是酱紫了,如果有错误请指正,当然没有错误是坠吼的(害怕.jpg).....


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值