链接: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. c# 限制同时启动多个实例程序运行

    using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using S ...

  2. Hadoop日记Day13---使用hadoop自定义类型处理手机上网日志

    测试数据的下载地址为:http://pan.baidu.com/s/1gdgSn6r 一.文件分析 首先可以用文本编辑器打开一个HTTP_20130313143750.dat的二进制文件,这个文件的内 ...

  3. Caffe上手教程

    Caffe上手教程 入门系列FAQ72 在Unbuntu上安装Caffe828 Windows下安装Caffe1.4K Caffe框架上手教程1.2K Caffe编译运行调试462 Caffe 电脑配 ...

  4. libgdx判断actor与circle是否重叠

    实质是检测矩形与circle是否重叠 基本函数,判断点是否在circle中 public static boolean IsInside( float x, float y, Circle circl ...

  5. 程序员大佬推荐的java学习路线

    作为我的第一篇博客,我第一个想到的就是在校时就看到的这篇文章.并且在之后的时间里自己都反复观看过,有时候这不单单是一篇学习路线,也是审视自己技术能力的里程碑,和激励自己的鞭挞绳. 先来个书籍清单: & ...

  6. Unity3D Shader 学习笔记(一):初识Shader

    第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...

  7. 科普贴 | 以太坊代币钱包MyEtherWallet使用教程,一步步教你玩转MEW

    MyEtherWallet 是一个以太坊的网页钱包,使用非常简单,打开网页就可以使用,源代码开源,不会在服务器上存储用户的钱包信息如私钥和密码.支持 Ledger Wallet.TREZOR 等硬件钱 ...

  8. oozie 编译与安装

    oozie:4.3.1  hadoop 2.7.6 hive编译使用2.0.0参与编译不通过,但是可以指定为1.2.0,编译可以通过,后期不使用hive的action即可(也可以使用,但是可能会出现异 ...

  9. SQL执行结果操作

    1. 返回执行结果中的一行 mysql_fetch_row() 返回执行结果的当前行的数值数组,执行这个函数后,结果指向下一行. e.g. $row = mysql_fetch_row($result ...

  10. PAT甲题题解-1008. Elevator (20)-大么个大水题,这也太小瞧我们做题者的智商了

    如题... #include <iostream> #include <cstdio> #include <algorithm> #include <cstr ...