c莫比乌斯函数_数论——容斥原理、莫比乌斯函数
数论——容斥原理、莫比乌斯函数由于某些玄学原因,有些公式的减号未显示,如果有的符号显示为空格,则默认为减号。
1、容斥原理:时间复杂度为
,下面会有证明。
举一个简单的例子:用韦恩图来思考,求
、
、
三个集合的原有元素的并集,那么结果为:
。
以此类推到
个圆的交集:用容斥原理的方法答案为所有单个集合的元素个数-所有两个集合互相交集的元素个数+所有三个集合互相交集的元素个数...
我们知道容斥原理公式一共涉及到的元素个数为:
。因为
,因此
,因此容斥原理公式一共涉及到的元素个数为
。关于此公式(
)的证明,我们可以假设等号左边为对于
个物品所有选法的总个数,等号右边考虑每个物品选与不选两种情况,因此等式成立。
因此容斥原理的时间复杂度为
。
容斥原理的证明:对于容斥原理
对于一个元素
,它在
个集合中,
,它本身被选择的次数为
。我们知道一个结论:
,因此对于每一个元素
,它只被计算了
次,证毕。
例题:AcWing 890. 能被整除的数
给定一个整数
和
个不同的质数
。请你求出
到
中能被
中的至少一个数整除的整数有多少个。
首先我们知道,在
个数中能被
整除的数的个数为
。
因此我们只需要根据容斥原理,求出可以被单个元素整除的个数之和-可以被两个元素整除的个数之和+可以被三个元素整除的个数之和...我们用位运算来求得答案,时间复杂度为
。
#include
#define int long long
using namespace std;
int p[20];
void work() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) cin >> p[i];
int res = 0;
for (int i = 1; i < 1 << m; i++) {
int t = 1, s = 0;
for (int j = 0; j < m; j++)
if (i >> j & 1) {
if (t * p[j] > n) {
t = -1;
break;
}
t *= p[j];
s++;
}
if (t != -1) {
if (s % 2) res += n / t;
else res -= n / t;
}
}
cout << res << endl;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int cas;
cas = 1;
while (cas--) work();
}
例题:AcWing 214. Devu和鲜花
有
个盒子,第
个盒子中有
枝花。同一个盒子内的花颜色相同,不同盒子内的花颜色不同。要从这些盒子中选出
枝花组成一束,求共有多少种方案。若两束花每种颜色的花的数量都相同,则认为这两束花是相同的方案。结果需对
取模之后方可输出。
我们先考虑:从
个盒子选
枝花,每个盒子的花的个数为无限个,问一共能选多少枝花?
此问题等价于从
个盒子选
花,那么每个盒子至少选
枝。那么此问题由等价于把
个点分成
份,我们可以用隔板法来做,一共有
个空隙,有
个板子,因此答案为
。
拓展到此问题,第
个盒子中有
枝花。那么我们可以反过来考虑,用总共的答案
减去其中第
个盒子被拿走了大于
枝花的方案。第
个盒子被拿走了大于
枝花的方案数为:假设此盒子已经被拿走了
枝花,那么等价于前面的问题,从
个盒子中共拿走
枝花的方案数,等价于从N个盒子拿走
的方案数,每个盒子至少被拿
枝。因此答案为
。
根据容斥原理来做,可知答案为总共的
减去所有
个盒子不满足的加上所有
个盒子不满足的减去所有
个盒子不满足的...
#include
#define int long long
using namespace std;
int A[20];
constexpr int mod = 1e9 + 7;
int down = 1;
int qmi(int a, int b, int p) {
int res = 1;
while (b) {
if (b & 1) res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
int C(int a, int b) {
if (a < b) return 0;
int up = 1;
for (int i = a; i > a - b; i--) up = i % mod * up % mod;
return up * down % mod;
}
void work() {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> A[i];
for (int j = 1; j <= n - 1; j++) down = j * down % mod;
down = qmi(down, mod - 2, mod);
int res = 0;
for (int i = 0; i < 1 << n; i++) {
int a = n + m - 1, b = n - 1;
int sign = 1;
for (int j = 0; j < n; j++)
if (i >> j & 1) {
sign *= -1;
a -= A[j] + 1;
}
res = (res + C(a, b) * sign) % mod;
}
cout << (res % mod + mod) % mod << endl;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int cas;
cas = 1;
while (cas--) work();
}
2、莫比乌斯函数:
我们举例一道经典的应用题,求
到
中与
互质的数的个数:那么根据容斥原理,设
为
到
中和
有公因子i的数的个数,答案为
,我们可以惊奇的发现,其答案为
。
我们可以根据线性筛质数在
的时间内算出前
个数的莫比乌斯数。
int primes[N], cnt;
bool st[N];
int mobius[N];
void init(int n) {
mobius[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
mobius[i] = -1;
}
for (int j = 0; primes[j] * i <= n; j++) {
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) {
mobius[t] = 0;
break;
}
mobius[t] = mobius[i] * -1;
}
}
}
AcWing 215. 破译密码
对于给定的整数
,
和
,有多少正整数对
,
,满足
,
,并且
。
组询问,
的数据范围为
。
根据数据的范围,我们可以推断出时间复杂度为
。
每次询问的问题等价于:有多少正整数对
,
,满足
,
,并且
。那么根据容斥原理:值为
,其答案为
,也就是
。我们可以推断出时间复杂度为
。
考虑把上述过程优化,发现,这个式子中虽然i要枚举
次,但是实际上因为整除的原因
的值很少,只有
个。
因为
是单调递减的,并且有的值相同,所以整个序列一共有有
个值。(证明:在分母为
到
之间,值的个数为
个值,在
到
之间,值的个数为
个值)。
设
表示
的取值不变的最大的
值,那么
,并且
,其中
。
证明
:
证明:
:
综上:将原来的序列分成
段,而且每次都会跳一段,所以总共会跳
次,时间复杂度就是
。
加上询问后总的时间复杂度为
。
#include
typedef long long ll;
using namespace std;
const int N = 50010;
int primes[N], cnt;
bool st[N];
int mobius[N], sum[N];
void init(int n) {
mobius[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
mobius[i] = -1;
}
for (int j = 0; primes[j] * i <= n; j++) {
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) {
mobius[t] = 0;
break;
}
mobius[t] = mobius[i] * -1;
}
}
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + mobius[i];
}
void work() {
int a, b, d;
cin >> a >> b >> d;
a /= d, b /= d;
int n = min(a, b);
ll res = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = min(n, min(a / (a / l), b / (b / l)));
res += (sum[r] - sum[l - 1]) * (ll)(a / l) * (b / l);
}
cout << res << endl;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
init(N - 1);
int cas;
cin >> cas;
while (cas--) work();
}
c莫比乌斯函数_数论——容斥原理、莫比乌斯函数相关推荐
- 编写分段函数子函数_编写自己的函数
编写分段函数子函数 PYTHON编程 (PYTHON PROGRAMMING) In Python, you can define your own functions. 在Python中,您可以定义 ...
- subtotal函数_星期五的Excel函数:将总计为SUBTOTAL的筛选列表
subtotal函数 The Excel SUM function does a great job of adding numbers on a worksheet, and it's probab ...
- js 实现2的n次方计算函数_密码杂凑函数的基本性质探讨
密码学研究的宗旨是保证数据和通信的机密性.完整性和认证性,其中完整性和认证性的实现依赖于一类关键的密码学函数---密码杂凑函数.密码杂凑函数通常用来计算数据的短"指纹"(也称杂凑值 ...
- mysql独有的函数_数据库之MySQL函数(一)
一.数学函数 1.绝对值函数 ABS(x) :返回 x 的绝对值 mysql> select ABS(2),ABS(-2.3),ABS(-22); 返回的结果如下: 数学学得好的大佬应该知道(本 ...
- 什么是python函数_什么是python函数
python函数是指组织好的.可重复使用的.用来实现单一或相关联功能的代码段.python函数包含系统中自带的一些函数.第三方函数.以及用户自定义的函数. 函数是可以实现一些特定功能的小方法或是小程序 ...
- python四大高阶函数_四大高阶函数
目录 1. 匿名函数 在我们需要一个函数但又不想费神的去命名一个函数的场合下使用,这就是匿名函数 1 f = lambda x,y,z:x+y+z2 defF(x,y,z):3 return x+y+ ...
- 画分段函数_秃头节:“函数”段子已出炉高中数学题型分析
高中数学函数题型整理解析版 函数图像 有关函数图象识别问题的常见题型及解题思路(1)由函数的定义域,判断图象左右的位置,由函数的值域,判断图象的上下位置:②由函数的单调性,判断图象的变化趋势:③由函数 ...
- ltrim函数_数据分析常用Excel函数
Excel是我们工作中经常使用的一种工具,对于数据分析来说,这也是处理数据最基础的工具.本文介绍数据分析中最常用的Excel函数. 查找匹配类 文本数据清洗类 日期类 逻辑运算类 计算统计类 一.查找 ...
- mysql数据库支持的函数_数据库MySQL--常见函数
函数:将一组逻辑语句封装在函数体中,对外暴露函数名 调用:select 函数名() from 表:(若用到表中的字段则家上'from 表') 函数分类: 1.单行函数(例:concate.leng ...
最新文章
- 虚拟方法及抽象方法在使用上的区别
- java 匿名类 实现接口_细谈 Java 匿名内部类 【分别 使用 接口 和 抽象类实现】...
- 电脑休眠和睡眠的区别_关机、睡眠、休眠有啥区别?微软说非特殊情况不要关机...
- jQuery 筛选
- linux下进程的创建代码,Linux下进程创建分析
- 快速排序和归并排序的区别,Python代码实现
- 【剑指 offer】(二十三)—— 从上往下打印二叉树(或曰层次遍历、广度优先遍历)
- 5.8 拉普拉斯算子和拉普拉斯矩阵,图拉普拉斯算子推导 意境级讲解
- JBPM工作流(八)——流程实例(PI)Process Instance
- MyEclipse 10.7(版本:eclipse 3.7.x-Indigo系列)安装activiti-eclipse-plugin插件(流程设计器)...
- 计算机管理模糊,电脑显示器显示有点模糊怎么办
- Chrome版本下载
- bc8-android导航,路畅A6导航刷机固件 4.09 CN-A6-GBDS-BC8-VIN-256-V1.51
- Andriod中插入百度广告的使用
- 用vim解压各种格式
- 习题:一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。
- 【Linux】MBR磁盘分区表只能有四个分区?
- 免费PPT模板下载(不定时更新)
- sublime text 3 调色板插件
- IT十年人生过客-十一-新挑战
热门文章
- JavaScript(JS)有一组英文歌曲,按照歌曲名称的字母顺序从“A”到“Z”顺序排列,保存在一个数组中。
- C#快速随机按行读取大型文本文件 - 磊的博客 - sanshi_leilei - 和讯博客
- 数据家新三板挂牌上市
- 【leetcode】搜索二维矩阵 II
- 如何用Python计算特征重要性?
- 我们都一样,不甘平凡又害怕努力
- GUI编程(java)
- 没人谈论的 3 种从 ChatGPT 赚钱的方法,我测试过的建立被动收入流的行之有效的方法
- 4g网络设置dns地址_4G网速越来越慢?别再去过多的责怪运营商,不妨试试这几个方法...
- 服装网上销售“美国版”——互动+体验=成功