ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))
终于讲到反演定理了,反演定理这种东西记一下公式就好了,反正我是证明不出来的~(~o ̄▽ ̄)~o
首先,著名的反演公式
我先简单的写一下o( ̄ヘ ̄*o)
比如下面这个公式
f(n) = g(1) + g(2) + g(3) + ... + g(n)
如果你知道g(x),蓝后你就可以知道f(n)了
如果我知道f(x),我想求g(n)怎么办
这个时候,就有反演定理了
反演定理可以轻松的把上面的公式变为
g(n) = f(1) + f(2) + f(3) + ... + f(n)
当然,我写的只是个形式,怎么可能这么简单。◕‿◕。
其实每一项再乘一个未知的函数就对了,但是这个函数我们不知道(不用担心,数学家已经帮我们解决了,我们直接用就可以了)
反演公式登场( >ω<)
c和d是两个跟n和r有关的函数
根据用法不同,c和d是不同的
一般数学家会先随便弄c函数
然后经过复杂的计算和证明,得到d函数
然后公式就可以套用了
正片开始
二项式反演公式
那个括号起来的就是组合数,我记得组合数那章我有说过
二项式反演也就是记住这个公式就算结束了
然后我们开始实战(/ω\)
容斥那章讲过的全错排(装错信封问题)
hdu 1465
http://acm.hdu.edu.cn/showproblem.php?pid=1465
设g(i)表示正好有i封信装错信封
那么全部的C(n, i)*g(i)加起来正好就是所有装信的情况,总共n!种情况
n! = Σ C(n, i)*g(i) (i从0到n)
那么f(n) = n!,所以f(x) = x!
那么我们要求g(n)
根据公式
g(n) = Σ (-1)^(n-i) * C(n, i) * f(i) (i从0到n)
那么就可以计算啦~\(≧▽≦)/~
AC代码:
#include<cstdio>
typedef long long LL;
int n, flag;
LL fac[];
LL ans;
void init(){
fac[] = ;
for(int i = ; i <= ; i ++) fac[i] = fac[i-] * i;
}
int main(){
init();
while(~scanf("%d", &n)){
ans = ;
flag = n & ? - : ;//起始符号
for(int i = ; i <= n; i ++){
ans += flag * fac[n] / fac[n-i];
flag = -flag;
}
printf("%I64d\n", ans);
}
}
是不是很好用但是不容易想到T_T
这也没有办法
再来一题吧
还是容斥那一章讲过的题目的
UVALive 7040
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5052
题意:给n盆花涂色,从m种颜色中选取k种颜色涂,保证正好用上k种颜色,你必须用上这k种颜色去涂满n个相邻的花,并且要求相邻花的颜色不同,求方案数。
(1 ≤ n, m ≤ 1e9 , 1 ≤ k ≤ 1e6 , k ≤ n, m)
首先,用k种颜色涂花,假如不考虑全部用上,那么总的方案数是多少
第一盆花有k种颜色选择,之后的花因为不能跟前一盆花的颜色相同,所以有k-1种选择
于是总方案数为k*(k-1)^(n-1)
我们设必须用 i 种颜色两两不相邻的涂花的方案数为 g(i)
那么
k*(k-1)^(n-1) = Σ C(k, i)*g(i) (i从1到k)
令f(k) = k*(k-1)^(n-1),那么f(x) = x*(x-1)^(n-1)
二项式反演公式出现了
所以g(k) = Σ (-1)^(k-i) * C(k, i) * f(i) (i从1到k)
最终的答案就是C(m, k) * g(k)
(这里m有1e9,C(m, k)直接用for循环算,直接for循环从m*(m-1)*...*(m-k+1)再乘k的阶乘的逆元)
AC代码:
#include<cstdio>
typedef long long LL;
const int N = + ;
const int MOD = (int)1e9 + ;
int F[N], Finv[N], inv[N];
LL pow_mod(LL a, LL b, LL p){
LL ret = ;
while(b){
if(b & ) ret = (ret * a) % p;
a = (a * a) % p;
b >>= ;
}
return ret;
}
void init(){
inv[] = ;
for(int i = ; i < N; i ++){
inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
}
F[] = Finv[] = ;
for(int i = ; i < N; i ++){
F[i] = F[i-] * 1ll * i % MOD;
Finv[i] = Finv[i-] * 1ll * inv[i] % MOD;
}
}
int comb(int n, int m){
if(m < || m > n) return ;
return F[n] * 1ll * Finv[n - m] % MOD * Finv[m] % MOD;
}
int main(){
init();
int T, n, m, k, ans, flag, temp;
scanf("%d", &T);
for(int cas = ; cas <= T; cas ++){
scanf("%d%d%d", &n, &m, &k);
ans = ;
flag = (k & ) ? : -;
//计算g(k)
for(int i = ; i <= k; i ++){
ans = (ans + 1ll * flag * comb(k, i) * i % MOD * pow_mod(i-, n-, MOD) % MOD) % MOD;
flag = -flag;
}
//接下来计算C(m, k)
temp = Finv[k];
for(int i = ; i <= k; i ++){
temp = 1ll * temp * (m-k+i) % MOD;
}
ans = ((1ll * ans * temp) % MOD + MOD) % MOD;
printf("Case #%d: %d\n", cas, ans);
}
}
做完两题之后就感觉二项式反演变得容易了,遇到题目还是要多想( ̄▽ ̄")
等等。。。做完两题的我突然发现二项式反演和容斥推倒出来的公式总是一样的。。。。。。(为什么有种被骗的感觉T_T)
ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))的更多相关文章
- acm数论之旅--中国剩余定理
ACM数论之旅9---中国剩余定理(CRT)(壮哉我大中华╰(*°▽°*)╯) 中国剩余定理,又名孙子定理o(*≧▽≦)ツ 能求解什么问题呢? 问题: 一堆物品 3个3个分剩2个 5个5个分剩3个 ...
- acm数论之旅--欧拉函数的证明
随笔 - 20 文章 - 0 评论 - 73 ACM数论之旅7---欧拉函数的证明及代码实现(我会证明都是骗人的╮( ̄▽ ̄)╭) https://blog.csdn.net/chen_ze_hua ...
- acm数论之旅--组合数(转载)
随笔 - 20 文章 - 0 评论 - 73 ACM数论之旅8---组合数(组合大法好(,,• ₃ •,,) ) 补充:全错排公式:https://blog.csdn.net/Carey_Lu/ ...
- acm数论之旅(转载) -- 逆元
ACM数论之旅6---数论倒数,又称逆元(我整个人都倒了( ̄﹏ ̄)) 数论倒数,又称逆元(因为我说习惯逆元了,下面我都说逆元) 数论中的倒数是有特别的意义滴 你以为a的倒数在数论中还是1/a吗 ( ...
- acm数论之旅--数论四大定理
ACM数论之旅5---数论四大定理(你怕不怕(☆゚∀゚)老实告诉我) (本篇无证明,想要证明的去找度娘)o(*≧▽≦)ツ ----------数论四大定理--------- 数论四大定理: 1.威 ...
- (暂时弃坑)(半成品)ACM数论之旅18---反演定理 第二回 Mobius反演(莫比乌斯反演)((づ ̄3 ̄)づ天才第一步,雀。。。。)
莫比乌斯反演也是反演定理的一种 既然我们已经学了二项式反演定理 那莫比乌斯反演定理与二项式反演定理一样,不求甚解,只求会用 莫比乌斯反演长下面这个样子(=・ω・=) d|n,表示n能够整除d,也就是d ...
- ACM数论之旅16---母函数(又名生成函数)(痛并快乐着(╭ ̄3 ̄)╭)
(前排出售零食瓜子) 前言: 母函数是个很难的东西,难在数学 而ACM中所用的母函数只是母函数的基础 应该说除了不好理解外,其他都是非常简单的 母函数即生成函数,是组合数学中尤其是计数方面的一个重要理 ...
- acm数论之旅(转载)--素数
https://www.cnblogs.com/linyujun/p/5198832.html 前言:好多学ACM的人都在问我数论的知识(其实我本人分不清数学和数论有什么区别,反正以后有关数学的知识我 ...
- ACM数论之旅10---大组合数-卢卡斯定理(在下卢卡斯,你是我的Master吗?(。-`ω´-) )
记得前几章的组合数吧 我们学了O(n^2)的做法,加上逆元,我们又会了O(n)的做法 现在来了新问题,如果n和m很大呢, 比如求C(n, m) % p , n<=1e18,m<=1e18 ...
随机推荐
- 一个简单的nodejs项目(cat-names)分析
https://github.com/sindresorhus/cat-names 一个非常简单的nodejs项目,用来方便的获取猫猫的名字: 安装: npm install --save cat-n ...
- 可视化分析 web 访问日志
内容目录 Python 基础 使用模块介绍 可视化组件 echarts 介绍 Web 访问日志 代码解读 讲师:KK 多语言混搭开发工程师,多年 PHP.Python 项目开发经验,曾就职 360.绿 ...
- bootStrap中Tab页签切换
关于$().tab()一般用来实现标签页和胶囊链接内容片段的切换,或是相关内容的页面导航: <ul class="nav nav-tabs" id="myTab&q ...
- 读书笔记:《HTML5开发手册》--figure、time、details、mark
这是补充HTML5基础知识的系列内容,其他为: 一.HTML5-- 新的结构元素 二.HTML5-- figure.time.details.mark 三.HTML5-- details活学活用 四. ...
- Winform下的语言国际化,几行代码轻松实现
最近做了一些关于winform的项目,需要用到winform的语言国际化,在初使化的时候用起来非常方便.可以参考一下: 核心逻辑: 预览效果演示: OK,以下是核心代码和操作流程 一,添加Langua ...
- android 图片二维码识别和保存(二)
续上一篇,开发图片二维码识别功能后,我们对功能进行性能分析内存占用显著提高了,不使用该功能内存占用大约是147M,使用这个功能多次以后,高达203M. 因此对功能进行研究,发现每次生成的图片没有即时的 ...
- C++将一个vector中的内容复制到另一个vector结尾
在使用vector容器的时候,需要将一个vector中的内容复制到另一个vector结尾,如何实现呢? 使用vector的insert方法 template <class InputIterat ...
- mongodb主从以及auth主从 配置详解
1.主服务器配置 #auth = true dbpath = /data/mongodb/db logpath = /data/mongodb/log/mongodb.log port = ...
- 快速删除docker中的容器
http://blog.csdn.net/cmzsteven/article/details/49230363
- 看oracle的sid
ps -ef|grep pmon 可以从进程名字里看到 也可以通过 sqlplus / as sysdbashow parameter instance_name