链接:vjudge

题目大意:有一排方格共 $n$ 个,现在有 $m$ 种颜色,要给这些方格染色,要求相邻两个格子的颜色不能相同。现在问恰好用了 $k$ 种颜色的合法方案数。答案对 $10^9+7$ 取模。$T$ 组数据。

$1\le T\le 300,1\le n,m\le 10^9,1\le k\le 10^6,k\le \min(n,m)$。大多数数据中 $k$ 很小。(smg啊……)


经典的二项式反演例题。

我们令 $f(x)$ 为一共有 $x$ 种颜色,恰好用了 $x$ 种颜色的方案数。

答案就是 ${m\choose k}f(k)$。因为任意选 $k$ 种颜色方案数是一样的。

这……似乎不太好算?

我们再令 $g(x)$ 为一共有 $x$ 种颜色,用了至多 $x$ 种颜色的方案数。

这个就不难算了。第一个格子可以随便填,就是 $x$ 种。后面的格子只要不和上一个颜色相同就行了,就是 $x-1$ 种。

乘法原理一下:$g(x)=x(x-1)^{n-1}$。$x=0$ 时这个式子是 $0$。

但是要注意,$x=n=1$ 时我们这样计算是 $0$,但是实际上是 $1$。为什么?$1\times 0^0$。所以我们要把 $0^0$ 看做 $1$,或者直接特判掉。

(但是不特判也能过,数据太水,这多组数据没用吧)

我们来想一想 $f$ 和 $g$ 有什么关系。很容易发现:$g(x)=\sum\limits^x_{i=0}{x\choose i}f(i)$。因为 $x$ 种颜色中随便选 $i$ 种都可以。

标准二项式反演形式。$f(x)=\sum\limits^x_{i=0}(-1)^{x-i}{x\choose i}g(i)$。

因为 $x\le 10^6$,所以阶乘和逆元都可以预处理,组合数就可以 $O(1)$ 了。此时 $f(x)$ 就可以 $O(x\log n)$ 算了。

现在问题就是算 $m\choose k$ 了。$m$ 达到了惊人的 $10^9$,模数又是个大数……怎么办?

我们发现 $m\choose k$ 可以表示成一种不常用的形式:$\frac{m(m-1)(m-2)...(m-k+1)}{k!}$。

此时分母是预处理过的,分子可以 $O(k)$ 算。这就完事了。

总时间复杂度 $O(Tk\log n)$。因为大多数数据中 $k$ 很小,所以可以跑过。

……这数据范围我给满分……

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=,mod=;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int t,n,m,k,fac[maxn],inv[maxn],invfac[maxn];
void init(){ //预处理阶乘,逆元,阶乘的逆元
fac[]=fac[]=inv[]=invfac[]=invfac[]=;
FOR(i,,){
fac[i]=1ll*fac[i-]*i%mod;
inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
invfac[i]=1ll*invfac[i-]*inv[i]%mod;
}
}
int C(int n,int m){
if(n<=) return 1ll*fac[n]*invfac[m]%mod*invfac[n-m]%mod; //n,m很小,可以直接算
int ans=invfac[m]; //分母是m的阶乘
ROF(i,n,n-m+) ans=1ll*ans*i%mod; //暴力乘上分子
return ans;
}
int qpow(int a,int b){ //快速幂
int ans=;
for(;b;b>>=,a=1ll*a*a%mod) if(b&) ans=1ll*ans*a%mod;
return ans;
}
int g(int x){
if(x== && n==) return ; //特判掉x=n=1
return 1ll*x*qpow(x-,n-)%mod;
}
int f(int x){
int ans=;
FOR(i,,x){
int v=1ll*C(x,i)*g(i)%mod;
if((x-i)&) ans=(ans-v+mod)%mod; //(-1)^(x-i)
else ans=(ans+v)%mod;
}
return ans;
}
int main(){
init();
t=read();
FOR(tt,,t){
n=read();m=read();k=read();
printf("Case #%d: %d\n",tt,int(1ll*C(m,k)*f(k)%mod)); //记得乘上C(m,k)
}
}

二项式反演

UVAlive-7040 color(组合数学,二项式反演)的更多相关文章

  1. 洛谷 P5400 - [CTS2019]随机立方体(组合数学+二项式反演)

    洛谷题面传送门 二项式反演好题. 首先看到"恰好 \(k\) 个极大值点",我们可以套路地想到二项式反演,具体来说我们记 \(f_i\) 为钦定 \(i\) 个点为极大值点的方案数 ...

  2. 2014ACM/ICPC亚洲区西安站现场赛 F color(二项式反演)

    题意:小球排成一排,从m种颜色中选取k种颜色给n个球上色,要求相邻的球的颜色不同,求可行的方案数,答案模1e9+7.T组数据,1<= n, m <= 1e9, 1 <= k < ...

  3. [LOJ3119][CTS2019|CTSC2019]随机立方体:组合数学+二项式反演

    分析 感觉这道题的计数方法好厉害.. 一个直观的思路是,把题目转化为求至少有\(k\)个极大的数的概率. 考虑这样一个事实,如果钦定\((1,1,1),(2,2,2),...,(k,k,k)\)是那\ ...

  4. UVALive 7040 Color (容斥原理+逆元+组合数+费马小定理+快速幂)

    题目:传送门. 题意:t组数据,每组给定n,m,k.有n个格子,m种颜色,要求把每个格子涂上颜色且正好适用k种颜色且相邻的格子颜色不同,求一共有多少种方案,结果对1e9+7取余. 题解: 首先可以将m ...

  5. UVALive 7040 Color

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

  6. 组合数+容斥原理 UVALive 7040 Color(14西安F)

    题目传送门 题意:n盆花涂色,相邻不能涂相同的颜色,从m中颜色选取k种颜色涂,保证正好有k种颜色 分析:从m中颜色选取k种就是C (m, k),然后第一个有k种选择,之后的都有k-1种选择,这样是不超 ...

  7. cf111D Petya and Coloring 组合数学,二项式反演

    http://codeforces.com/contest/111/problem/D Little Petya loves counting. He wants to count the numbe ...

  8. ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))

    终于讲到反演定理了,反演定理这种东西记一下公式就好了,反正我是证明不出来的~(-o ̄▽ ̄)-o 首先,著名的反演公式 我先简单的写一下o( ̄ヘ ̄*o) 比如下面这个公式 f(n) = g(1) + g ...

  9. [模板] 容斥原理: 二项式反演 / Stirling 反演 / min-max 容斥 / 子集反演 / 莫比乌斯反演

    //待更qwq 反演原理 二项式反演 若 \[g_i=\sum_{j=1}^i {\binom ij} f_j\] , 则有 \[ f_i=\sum_{j=1}^i (-1)^{i-j} {i \ch ...

随机推荐

  1. iterms 快捷键

    标签 新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 command + 左右方向键 切换全屏:command + enter 查找:comma ...

  2. JavaEE笔记(十二)

    代理的三种配置 beans配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=& ...

  3. [BZOJ4857][JSOI2016]反质数序列[最大点独立集]

    题意 在长度为 \(n\) 的序列 \(a\) 中选择尽量长的子序列,使得选出子序列中任意两个数的和不为质数. \(n\leq3000\ ,a_i\leq10^5\). 分析 直接按照奇偶性建立二分图 ...

  4. 后端自动构建前端css和js

    引子: 别的复杂前端开发技术不会,用得多的还是手写代码,手动处理. 3年前手写合并压缩js和css文件的asp脚本代码目前还能正常运行,也就没有多大使用别的技术的动力. 直到近期被一个问题纠结着,今天 ...

  5. github协同开发

    看官请移步GitHub团队项目合作流程 本文是上述链接的截图,担心哪天作者不小心删除了,备一份在自己这里,仅为自己看着方便.侵权请告知

  6. java File读取文件始终不存在的问题分析

    先上图: 如图,f1 始终能读到该文件,使用的是绝对路径 f2 却是相对路径. 感觉很奇怪,明明一模一样的代码为什么会产生不同的结果呢? 首先想到的是是不是有什么特殊字符.. 拿到notepad++中 ...

  7. jmeter分布式压力测试之添加压力机

    前提:多台电脑可以互相ping通 1.jmeter的bin目录下的jmeter.properties配置文件里面remote_hosts添加测试机的 IP:端口号,用英文“,”逗号间隔例如:remot ...

  8. 利用matlab写一个简单的拉普拉斯变换提取图像边缘

    可以证明,最简单的各向同性微分算子是拉普拉斯算子.一个二维图像函数 f(x,y) 的拉普拉斯算子定义为 ​ 其中,在 x 方向可近似为 ​ 同理,在 y 方向上可近似为 ​ 于是 我们得到满足以上三个 ...

  9. Python进阶量化交易场外篇3——最大回撤评价策略风险

    新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...

  10. 1093. Count PAT’s (25)-统计字符串中PAT出现的个数

    如题,统计PAT出现的个数,注意PAT不一定要相邻,看题目给的例子就知道了. num1代表目前为止P出现的个数,num12代表目前为止PA出现的个数,num123代表目前为止PAT出现的个数. 遇到P ...