uvalive7040 / cf gym 100548 Color(2014西安区域赛F题)
2015-08-09 13:40
323 查看
Source
CF GYM 100548UVALIVE 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; }
相关文章推荐
- Android手势密码LockPatternView、LockPasswordUtils、LockPatternUtils等分析
- Oracle 表连接 导致排序错乱
- SubMenu子菜单
- maven聚合和继承
- 一张地图,告诉你NodeJS命令行调试器语句
- 多线程的使用——Thread类和Runnable接口
- hibernate中的通用<K,V>查询法
- I Hate It
- 虚拟内存和内存映射
- 基于OpenCL的深度学习工具:AMD MLP及其使用详解
- 《学习opencv》笔记——矩阵和图像处理——cvMinManLoc,cvMul,cvNot,cvNorm and cvNormalize
- @SuppressWarinings, @TargetApi, @SuppressLint, @ViewInject
- HDU 5365(不是地球人)
- 利用Sqoop将数据从数据库导入到HDFS
- HDU 1114
- DevExpress XPO 常用功能
- NavigationView+Toolbar
- MySQL中的UUID
- 分层驱动将IRP分解成多个IRP
- LDA主题模型