传送门
英文题目:

Recently, Mr. Big recieved n owers from his fans. He wants to recolor those owers with m colors. The
owers are put in a line. It is not allowed to color any adjacent owers with the same color. Flowers i and
i + 1 are said to be adjacent for every i, 1 ≤ i < n. Mr. Big also wants the total number of different
colors of the n owers being exactly k.
Two ways are considered different if and only if there is at least one ower being colored with different
colors.

插图:

题目大意:
首先有T组数据,每组数据有 3 个数 n, m, k,分别代表一共有 n 个方格,m种颜色,而我们要 恰好(注意是恰好) 使用 k 中颜色对这些方格进行涂色,并且保证的是每两个相邻的方格的颜色必须是不一样的。

解题思路:
首先拿过这个题来 不要急着就是说一眼就做出来,所以我们先对它分析一下,我们要从 m 种颜色中选出 k 个进行涂色 所以用的方法数就是 C(m,k),然后对这 n 个方格涂色,第一个 有 k 种选择, 而后边的 n-1 个方格中只有 k-1 种选择,所以 就有公式

S=C(m,k)∗k∗(k−1)n−1

S = C(m,k)*k*(k−1)^{n−1}
然后这并不是最后的结果,这是 所选的颜色不超过 k 种的方法数,而不是 恰好 用 k 种颜色的,然后就可以用容斥原理来求了,假设集合 Ai 表示 i 号颜色不被选,所以 我们要求的结果

ans=S−(A1⋃A2⋃...⋃An)

ans = S - (A1 ⋃ A2 ⋃... ⋃ An)
A1 ⋃ A2 ⋃… ⋃ An 就得通过容斥原理来做啦。。。
根据上面我们可以求出从 k 种颜色种选 k-i个,剩下的就是 n-1个方格中有 k-i-1中选择。所以这个公式就是:

C(k,k−i)∗(k−i)∗(k−i−1)n−1

C(k,k-i) * (k-i) * (k-i-1)^{n-1}
然后考虑的就是奇数加 偶数减就行了。然后再注意一下细节问题:
1.怎么样求C(m,k),这个就是用到 递推公式了首先给出一个公式

C(x,i)=C(x,i−1)∗n−i+1i

C(x,i) = C(x,i-1)*\frac{n-i+1}{i}
这个公式很好推导:

C(n,i)=n!i!∗(n−i)!=n!i∗(i−1)!∗(n−i+1)!/(n−i+1)=n!(i−1)!∗(n−i+1)!∗n−i+1i=C(x,i−1)∗n−i+1i

C(n,i) = \frac{n!}{i!*(n-i)!} \\= \frac{n!}{i*(i-1)!*(n-i+1)!/(n-i+1)}\\= \frac{n!}{(i-1)!*(n-i+1)!}*\frac{n-i+1}{i}\\= C(x,i-1)*\frac{n-i+1}{i}
所以根据这个公式我们可以打个表就能算 C(m,k)和 C(k,i)了
2.求逆元的问题。因为 C(x,i)=C(x,i-1)*(x-i+1)/i可以通过扩展欧几里得算法来算,但是要记得的是要用一个数组保存一下 每一个的逆元,要不然每次调用函数的话 会超时。
3.就是容斥的详细过程了。记住一点 奇数加偶数减就行
接下来就是编写程序了,详见我的代码。

My Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>using namespace std;
const int MOD = 1e9+7;
const int MAXN = 1e6+5;
typedef long long LL;
LL Scan()///输入外挂
{LL res=0,ch,flag=0;if((ch=getchar())=='-')flag=1;else if(ch>='0'&&ch<='9')res=ch-'0';while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';return flag?-res:res;
}void Out(LL a)///输出外挂
{if(a>9)Out(a/10);putchar(a%10+'0');
}///快速幂
LL quick_mod(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 Exgcd(LL a, LL b, LL &x, LL &y)
{if(b == 0){x = 1;y = 0;return;}LL x1, y1;Exgcd(b, a%b, x1, y1);x = y1;y = x1 - (a/b)*y1;
}
LL Inv[MAXN];///放逆元的数组
///得到逆元
void Get_Inv()
{Inv[1] = 1;for(int i=2; i<MAXN; i++){LL y;Exgcd(i, MOD, Inv[i], y);Inv[i] = (Inv[i]%MOD+MOD)%MOD;}
}
/**     得到组合数,通过递推公式C(m,i) = C(m,i-1)*(m-i+1)/i;    **/
LL cm[MAXN], ck[MAXN];///分别是m的组合数 和 k 的组合数
LL n, m, k;void Get_Fac()
{cm[0] = ck[0] = 1;for(int i=1; i<=k; i++){cm[i] = (cm[i-1]%MOD * (m-i+1)%MOD * Inv[i]%MOD) % MOD;ck[i] = (ck[i-1]%MOD * (k-i+1)%MOD * Inv[i]%MOD) % MOD;}
}
/**
11
1000000000 1000000000 1000000
**/
int main()
{Get_Inv();int T;T = Scan();for(int cas=1; cas<=T; cas++){n = Scan();m = Scan();k = Scan();Get_Fac();LL ret = 1;LL ans = 0;for(LL i=k; i>=1; i--){ans = (ans+ret*i*ck[i]%MOD*quick_mod(i-1,n-1)%MOD+MOD)%MOD;ret = -ret;//cout<<ans<<" ";}ans = ans * cm[k] % MOD;printf("Case #%d: %lld\n",cas,ans);}return 0;
}

UVALive 7040 Color (容斥原理 + 组合数学递推公式 + 求逆元 + 基础数论)相关推荐

  1. UVALive 7040 Color

    题目链接:LA-7040 题意为用m种颜色给n个格子染色.问正好使用k种颜色的方案有多少. 首先很容易想到的是\( k * (k-1)^{n-1}\),这个算出来的是使用小于等于k种颜色给n个方格染色 ...

  2. 扩展欧几里得算法求逆元_从辗转相除法到求逆元,数论算法初体验

    今天是算法和数据结构专题的第22篇文章,我们一起来聊聊辗转相除法. 辗转相除法又名欧几里得算法,是求最大公约数的一种算法,英文缩写是gcd.所以如果你在大牛的代码或者是书上看到gcd,要注意,这不是某 ...

  3. 基础数论(3)同余、逆元

    同余和逆元 本篇博客将介绍同余和逆元,以及求逆元的三种方法(因为快速幂是本菜鸡在很久之前c语言还没学完的时候扣了一晚上看懂了,所以默认大家都会了) 放到一起总结一下.拖了好久的说... 然后,开始了. ...

  4. [组合数学] NC13611树 (逆元的计算)

    题面    link 有一颗树,树有n个结点.有k种不同颜色的染料给树染色.一个染色方案是合法的,当且仅当对于所有相同颜色的点对(x,y),x到y的路径上的所有点的颜色都要与x和y相同.请统计方案数. ...

  5. 【训练题22:线性求逆元】【模板】乘法逆元 | 洛谷 P3811

    [模板]乘法逆元 难度 普及/提高\color{yellow}普及/提高普及/提高 板子题,给出两种方法 题意 给 n,pn,pn,p 求出所有 i∈[1,n]i\in[1,n]i∈[1,n]在模 p ...

  6. 【数论】求逆元的四种方法

    逆元的定义 给定正整数a,p,如果有 ,且a与p互质,则称x的最小正整数解为a模p的逆元. 一.扩展欧几里得算法 使用条件:基本上通用,不要求p为质数,且效率高,时间复杂度为. 证明过程:有解的条件是 ...

  7. BZOJ 3456: 城市规划 [多项式求逆元 DP]

    题意: 求出n个点的简单(无重边无自环)无向连通图数目. 方案数mod 1004535809(479 * 2 ^ 21 + 1)即可. n<=130000 DP求方案 g(n) n个点所有图的方 ...

  8. 线性求逆元模板_ACM 数论基本模板

    ACM 数论基本模板 1.欧几里得 求最大公约数,最小公倍数 (1)递归的写法:int gcd(int a,int b) {return b?gcd(b,a%b):a;} (2)辗转相除法: int ...

  9. 求逆元(线性求逆元)及其扩展欧几里得

    线性求逆元模板: int inv[maxn]; void initInverse(){inv[1] = 1;for(int i = 2; i <= maxn; i++)inv[i] = (p - ...

最新文章

  1. java线程占用CPU_在windows下揪出java程序占用cpu很高的线程并完美解决
  2. java中有几种内部类,Java中的四种内部类
  3. 查找两个已经排好序的数组的第k大的元素
  4. Java中的程序设计模式--单例与多例
  5. Web框架之Django_03 路由层了解(路有层 无名分组、有名分组、反向解析、路由分发 视图层 JsonResponse,FBV、CBV、文件上传)
  6. C 控制父、子进程的先后顺序执行
  7. UMEditor调整文本编辑器的组件位置的方法
  8. 《RabbitMQ 实战指南》第四章 RabbitMQ进阶(上)
  9. 【AdaBoost算法】积分图代码实现
  10. Chrome 谷歌浏览器账户无法登录、注册
  11. pixhawk position_estimator_inav.cpp再分析
  12. java 解压带密码rar_Java解压和压缩带密码的zip文件过程详解
  13. Linux搭建Nacos及Nacos集群
  14. 关于数据的笑话 30 则
  15. DSPE;CAS:1069-79-0 ;二硬脂酰基磷脂酰乙醇胺;功能化磷脂
  16. ArithmeticException算数异常
  17. kubernetes之volumes使用
  18. 中央直属企业名单【中国级别最高的169家企业】(转)--找工作按这个来
  19. DPU芯片企业中科驭数加入龙蜥社区,构建异构算力生态
  20. 【PTA-训练day20】L2-032 彩虹瓶 + L1-080 乘法口诀数列

热门文章

  1. The ADO.NET provider with invariant name “MySql.Data.MySqlClient” is either not registered
  2. input失去焦点验证格式_表单验证之失去焦点校验
  3. 基于Matlab实现硬币计数
  4. Linux系列:Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password
  5. sparse coo_matrix和torch coo_matrix转换
  6. vipjr好不好,零基础的孩子来分享经验
  7. 因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 abou t_Execution_Policies
  8. ORCA(RVO2)算法优化整理版
  9. java文件上传以及上传至FastDFS
  10. webRTC 实现人脸识别