Codeforces GYM 100548 F - Color (2014年西安站F题)

这是一道关于涂色问题的竞赛题目,要求在N朵花上使用M种颜色,相邻花朵颜色不能相同,并恰好使用K种颜色。通过组合数学和容斥原理,可以得出公式:F(i)=Ciki(i−1)n−1,并通过求和计算出使用K种颜色的方案数。
摘要由CSDN通过智能技术生成

题意: N 朵花,有M种颜色可用,要求给他们涂色,相邻的话颜色不同。要求正好使用 K 种颜色。
题解:选K种颜色是 Ckm ,记 F(i) 为选了 K 种颜色后,使用不超过i种颜色的方案。第一朵花有 i 种选择,后面N1朵的花的颜色除了前一朵花的颜色之外都可以选,总的就是 F(i)=Ciki(i1)n1
要求出正好 K 种颜色的,就要利用容斥原理,用不超过K种的 - 不超过 (K1) 种的 + 不超过 (K2) 种的 - 不超过 (K3) 种的…
答案就是 Ckm(F(k)F(k1)+F(k2)...)=Ckmki=1(1)kiF(i)

题目地址
这里写图片描述

#include <iostream>
#include <cstring>
#include <cstdio>
#define prt(k) cout<<#k" = "<<k<<endl;
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const int N = 1000005;
ll inv[N];
ll C[N];
ll n, m, k;
ll powmod(ll a, ll n)
{
    ll ret = 1;
    for (; n; n>>=1, a=a*a%mod)
        if (n&1)
        ret = ret*a%mod;
    return ret % mod;
}
void init(ll m, ll k)
{
    C[0] = 1;
    for (ll i=1;i<=k;i++)
        C[i] = ( C[i-1] * (m-i+1) %mod )* inv[i]% mod;
}
ll F(ll i)
{
    return (i*C[i] %mod )* powmod(i-1, n-1) % mod;
}
int main()
{
    memset(inv, 0, sizeof inv);
    for (int i=1;i<N;i++) inv[i] = powmod(i, mod-2)%mod;
    int re, ca=1; scanf("%d", &re);
    while (re--)
    {
        scanf("%I64d %I64d %I64d", &n, &m, &k);
        ll sig = 1;
        init(m, k);
        ll ans = C[k]%mod;
        ll tmp = 0;
        memset(C, 0, sizeof C);
        init(k, k);
        for (ll i=k;i>=1;i--)
        {
            tmp = (tmp + sig * F(i) + mod) % mod;
            sig = -sig;
        }
        ans = ans * tmp % mod;
        printf("Case #%d: %I64d\n", ca++, ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值