您的位置:首页 > 其它

uvalive7040 / cf gym 100548 Color(2014西安区域赛F题)

2015-08-09 13:40 323 查看

Source

CF GYM 100548

UVALIVE 7040

题意

n个格子排成一行,有m种颜色,问用恰好k种颜色进行染色,使得相邻格子颜色不同的方案数。

k≤106n,m≤109

分析

在网上看到的几篇解题报告好像没讲清楚为什么是容斥(反正我没看懂。。),所以我也写一篇。

首先,我们可以从m个颜色中取出k个,即Ckm。

接着容易想到 k∗(k−1)n−1, 这个是使用不超过k种颜色的所有方案。但我们要求的是恰好使用k种颜色。

假设选出的k种颜色标号为1,2,3,…, k,那么记 Ai 为不使用颜色i的方案数,求的就是 |S|−|A1⋃A2⋃⋯⋃An| 。也就是反过来考虑,我们不考虑用了哪些颜色,我们考虑哪些颜色没用!减去所有有没使用颜色的方案的并集,剩下的方案就是使用了所有k种颜色的方案。上式中的 |S| 即 k∗(k−1)n−1 ,后者就可以用容斥原理来求了。注意到我们只是给颜色标了个号,所以后面每一项的应为 Cik∗(k−i)∗(k−i−1)n−1 的形式,即选出i个不使用的颜色,用剩余颜色去涂的方案数。完整式子写起来比较麻烦就不写了,可以参考其他blog。

代码

/*************************************************************************
> File Name: uvalive_7040.cpp
> Author: james47
> Mail:
> Created Time: Sat Aug  8 08:47:40 2015
************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

const int mod = (int)1e9+7;
int pow_mod(int a, int exp){
int ret = 1;
while(exp){
if (exp&1) ret = (long long)ret * a % mod;
a = (long long)a * a % mod;
exp >>= 1;
}
return ret;
}
int c[(int)1e6+100];
int inv[(int)1e6+100];
int cal(int n, int m, int k){
if (k == 1 && n == 1) return m;
if (k == 1 && n > 1) return 0;
int ret = 1, lim = min(k, m - k);
for (int i = 1; i <= lim; i++) ret = (long long)ret * (m-i+1) % mod * inv[i] % mod;
c[0] = 1;
for (int i = 1; i <= k; i++) c[i] = (long long)c[i-1] * (k-i+1) % mod * inv[i] % mod;
int tmp, tot = (long long)k * pow_mod(k-1, n-1) % mod;
for (int i = 1; i+1 < k; i++){
tmp = (long long)c[i] * (k-i) % mod * pow_mod(k-i-1, n-1) % mod;
if (i&1){
tot = tot - tmp;
if (tot < 0) tot += mod;
}
else{
tot = tot + tmp;
if (tot >= mod) tot -= mod;
}
}
ret = (long long)ret * tot % mod;
return ret;
}
void init(){
inv[1] = 1;
for (int i = 2; i <= 1000000; i++){
inv[i] = (long long)(mod - mod/i) * inv[mod % i] % mod;
}
}
int T, n, m, k;
int main()
{
init();
scanf("%d", &T); int cas = 0;
while(T--){
scanf("%d %d %d", &n, &m, &k);
printf("Case #%d: %d\n", ++cas, cal(n, m, k));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: