'commit'
This commit is contained in:
44
TangDou/AcWing/Math/RongChi/HDU1796.cpp
Normal file
44
TangDou/AcWing/Math/RongChi/HDU1796.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
#define int long long
|
||||
#define endl "\n"
|
||||
|
||||
const int N = 15;
|
||||
vector<int> p;
|
||||
|
||||
// 最小公倍数
|
||||
int lcm(int a, int b) {
|
||||
return a * b / __gcd(a, b);
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int n, m;
|
||||
while (cin >> m >> n) { // n个数,求[1~m)中有多少个数能被整除集合中的数字整除
|
||||
m--; // small than m 注意细节
|
||||
p.clear(); // 多组测试数据,注意清0
|
||||
|
||||
for (int i = 0; i < n; i++) { // n个数字组成的序列
|
||||
int x;
|
||||
cin >> x;
|
||||
if (x) p.push_back(x); // 排除掉数字0,0不能做除数
|
||||
}
|
||||
|
||||
int s = 0;
|
||||
for (int i = 1; i < (1 << p.size()); i++) {
|
||||
int cnt = 0;
|
||||
int t = 1;
|
||||
for (int j = 0; j < p.size(); j++) {
|
||||
if (i >> j & 1) {
|
||||
cnt++;
|
||||
t = lcm(t, p[j]); // 这里不是简单的相乘,而是求的最小公倍数
|
||||
}
|
||||
}
|
||||
if (cnt & 1)
|
||||
s += m / t;
|
||||
else
|
||||
s -= m / t;
|
||||
}
|
||||
cout << s << endl;
|
||||
}
|
||||
}
|
||||
54
TangDou/AcWing/Math/RongChi/HDU4135.cpp
Normal file
54
TangDou/AcWing/Math/RongChi/HDU4135.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
#define endl "\n"
|
||||
|
||||
// 返回1-m中与n互素的数的个数
|
||||
vector<int> p;
|
||||
int cal(int n, int m) {
|
||||
// 多组测试数据,清空
|
||||
p.clear();
|
||||
|
||||
// 对n分解质因数
|
||||
for (int i = 2; i * i <= n; i++) {
|
||||
if (n % i == 0) {
|
||||
p.push_back(i);
|
||||
while (n % i == 0) n /= i;
|
||||
}
|
||||
}
|
||||
if (n > 1) p.push_back(n); // 最后一个大因子,也加入
|
||||
|
||||
int s = 0; // 1到m中与n不互素的数的个数
|
||||
|
||||
// 枚举子集,不能有空集,所以从1开始
|
||||
for (int i = 1; i < 1 << p.size(); i++) { // 从1枚举到(2^素因子个数)
|
||||
int cnt = 0;
|
||||
int t = 1;
|
||||
for (int j = 0; j < p.size(); j++) { // 枚举每个素因子
|
||||
if (i & (1 << j)) { // 有第i个因子
|
||||
cnt++; // 计数
|
||||
t *= p[j]; // 乘上这个质因子
|
||||
}
|
||||
}
|
||||
// 容斥原理
|
||||
if (cnt & 1) // 选取个数为奇数,加
|
||||
s += m / t;
|
||||
else // 选取个数为偶数,减
|
||||
s -= m / t;
|
||||
}
|
||||
return m - s; // 返回1-m中与n互素的数的个数
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int T, ca = 0;
|
||||
cin >> T;
|
||||
|
||||
while (T--) {
|
||||
int m, a, b;
|
||||
cin >> a >> b >> m; // 求区间[a,b]中与m互素的数字个数
|
||||
// 计算[1,a-1]之间与m互素的个数
|
||||
// 计算[1, b]之间与m互素的个数
|
||||
int ans = cal(m, b) - cal(m, a - 1);
|
||||
printf("Case #%d: %lld\n", ++ca, ans);
|
||||
}
|
||||
}
|
||||
85
TangDou/AcWing/Math/RongChi/HDU4135.md
Normal file
85
TangDou/AcWing/Math/RongChi/HDU4135.md
Normal file
@@ -0,0 +1,85 @@
|
||||
[题目链接](http://acm.hdu.edu.cn/showproblem.php?pid=4135)
|
||||
https://blog.csdn.net/qq_40507857/article/details/82788443
|
||||
|
||||
> 题意:求区间`[a,b]`中与`m`互素的数字个数
|
||||
|
||||
### 一、题目分析
|
||||
|
||||
考虑`[1,a-1]`和`[1,b]`两个区间与`m`互素的个数,答案就是二者之差(**类似前缀和?**)。
|
||||
|
||||
<font color='red'><b>容斥原理经典问题</b></font>:求`1-n`中与`m`互素的数的个数
|
||||
|
||||
互素的个数等于总数减去不互素的个数,如果$1-n$中某个数与$m$不互素,那么一定可以被$m$的某个因子整除,所以先枚举$m$的所有素因子。
|
||||
|
||||
举个例子,$m=12,n=8$,$12$的素因子是$2,3$,
|
||||
|
||||
$1\sim 8$中有几个是$2$的倍数呢?$S_2=8/2=4$;
|
||||
$1\sim 8$中有几个是$3$的倍数呢?$S_3=8/3=2$;
|
||||
|
||||
$1\sim 8$之间与$12$互素的个数是$2+4=6$个数字吗?
|
||||
|
||||
$1\sim 8$之间与$12$不互素的是$2,3,4,6,8$,共$5$个数字,这是因为同为$2$和$3$的倍数的$6$被计算了两次,所以要再减去一次$S_6=8/6=1$,结果是 $$\large 8/2+8/3-8/(2*3)=4+2-1=5$$
|
||||
|
||||
这是经典的容斥原理啊,如果是奇数个组合,那么符号是`+`;如果是偶数个组合,那么符号是`-`;
|
||||
|
||||
|
||||
### 二、实现代码
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
typedef long long LL;
|
||||
|
||||
//返回1-m中与n互素的数的个数
|
||||
vector<LL> p;
|
||||
LL cal(LL n, LL m) {
|
||||
p.clear();
|
||||
for (int i = 2; i * i <= n; i++) {
|
||||
if (n % i == 0) {
|
||||
p.push_back(i);
|
||||
while (n % i == 0) n /= i;
|
||||
}
|
||||
}
|
||||
if (n > 1) p.push_back(n); //求n的素因子
|
||||
|
||||
int num = p.size(); //素因子的个数
|
||||
LL s = 0; // 1到m中与n不互素的数的个数
|
||||
|
||||
//枚举子集,不能有空集,所以从1开始
|
||||
for (LL i = 1; i < 1 << num; i++) { //从1枚举到(2^素因子个数)
|
||||
LL cnt = 0;
|
||||
LL t = 1;
|
||||
for (LL j = 0; j < num; j++) { //枚举每个素因子
|
||||
if (i & (1 << j)) { //有第i个因子
|
||||
cnt++; //计数
|
||||
t *= p[j]; //乘上这个质因子
|
||||
}
|
||||
}
|
||||
//容斥原理
|
||||
if (cnt & 1) //选取个数为奇数,加
|
||||
s += m / t;
|
||||
else //选取个数为偶数,减
|
||||
s -= m / t;
|
||||
}
|
||||
return m - s; //返回1-m中与n互素的数的个数
|
||||
}
|
||||
|
||||
int main() {
|
||||
//加快读入
|
||||
ios::sync_with_stdio(false);
|
||||
cin.tie(0);
|
||||
cout.tie(0);
|
||||
|
||||
int T, ca = 0;
|
||||
cin >> T;
|
||||
|
||||
while (T--) {
|
||||
LL m, a, b;
|
||||
cin >> a >> b >> m; //求区间[a,b]中与m互素的数字个数
|
||||
//计算[1,a-1]之间与m互素的个数
|
||||
//计算[1, b]之间与m互素的个数
|
||||
LL ans = cal(m, b) - cal(m, a - 1);
|
||||
printf("Case #%d: %lld\n", ++ca, ans);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
34
TangDou/AcWing/Math/RongChi/Test.cpp
Normal file
34
TangDou/AcWing/Math/RongChi/Test.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int INF = 0x3f3f3f3f;
|
||||
typedef long long LL;
|
||||
const int N = 20;
|
||||
int a[N];
|
||||
int n, m;
|
||||
int res;
|
||||
|
||||
int main() {
|
||||
scanf("%d %d", &n, &m);
|
||||
for (int i = 0; i < m; i++) scanf("%d", &a[i]);
|
||||
for (int i = 1; i < 1 << m; i++) {
|
||||
int s = 1, c = 0;
|
||||
for (int j = 0; j < m; j++)
|
||||
if (i >> j & 1) {
|
||||
if ((LL)s * a[j] > n) {
|
||||
s = 0;
|
||||
break;
|
||||
}
|
||||
s *= a[j];
|
||||
c++;
|
||||
}
|
||||
if (s) {
|
||||
if (c & 1)
|
||||
res += n / s;
|
||||
else
|
||||
res -= n / s;
|
||||
}
|
||||
}
|
||||
printf("%d\n", res);
|
||||
return 0;
|
||||
}
|
||||
1
TangDou/AcWing/Math/RongChi/UVA11806.cpp
Normal file
1
TangDou/AcWing/Math/RongChi/UVA11806.cpp
Normal file
@@ -0,0 +1 @@
|
||||
// TODO
|
||||
62
TangDou/AcWing/Math/RongChi/取整函数及其性质.md
Normal file
62
TangDou/AcWing/Math/RongChi/取整函数及其性质.md
Normal file
@@ -0,0 +1,62 @@
|
||||
## 取整函数及其性质
|
||||
|
||||
### 1、取整函数定义及分类
|
||||
|
||||
取整函数是一类将实数映射到相近的整数的函数。
|
||||
|
||||
常用的取整函数有两个,分别是**下取整**函数和**上取整**函数。
|
||||
|
||||
|
||||
* [Floor and ceiling functions - Wikipedia](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions#Number_of_digits)
|
||||
|
||||
* [Useful Properties of the Floor and Ceil Functions](https://janmr.com/blog/2009/09/useful-properties-of-the-floor-and-ceil-functions/)
|
||||
|
||||
下取整函数在数学中一般记作$\left \lfloor x \right \rfloor$,比自己小的最大整数,在计算机科学中一般记作$floor(x)$;
|
||||
|
||||
上取整函数在数学中一般记作$\left \lceil x \right \rceil$,比自己大的最小整数,在计算机科学中一般记作$ceil(x)$。
|
||||
|
||||
### 2、性质:(仅列举计算机学习中经常用到的性质)
|
||||
* 任意实数$x$,有: $x−1<⌊x⌋≤x≤⌈x⌉<x+1$
|
||||
<br>
|
||||
|
||||
* 下取整函数为等幂运算: $\left \lfloor \left \lfloor x \right \rfloor \right \rfloor = \left \lfloor x \right \rfloor.$
|
||||
<br>
|
||||
* 对任意的整数 $k$ 和任意实数 $x$,$\left \lfloor k+x \right \rfloor = k + \left \lfloor x \right \rfloor$
|
||||
<br>
|
||||
* 一般的数值修约规则可以表述为将$x$映射到 $floor(x + 0.5)$。
|
||||
<br>
|
||||
* $\left \lceil x \right \rceil = - \left \lfloor -x \right \rfloor$
|
||||
<br>
|
||||
|
||||
* 对于整数$k$有:$\left \lfloor k/2 \right \rfloor + \left \lceil k/2 \right \rceil = k$
|
||||
|
||||
### 3、对数与取整函数的关系
|
||||
二者关系为:
|
||||
|
||||
$\left \lceil \log (x+1) \right \rceil = \left \lfloor \log x \right \rfloor +1, x\in Z, x\geqslant 1$
|
||||
|
||||
**证明:**
|
||||
|
||||
令$m = \left \lfloor \log x \right \rfloor$,
|
||||
|
||||
则 $m \leq \log x < m+1$ ①
|
||||
|
||||
由式①可得
|
||||
|
||||
$2^{m} \leq x < 2^{m+1}$ ②,
|
||||
|
||||
进而可得
|
||||
|
||||
$2^{m} < x+1 \leq 2^{m+1}$
|
||||
|
||||
因为 $x\in Z$, 所以 $m < \log (x+1) \leq m+1$.
|
||||
|
||||
所以 $\left \lceil \log (x+1) \right \rceil = m+ 1= \left \lfloor \log x \right \rfloor + 1$.
|
||||
|
||||
### 4、向下取整与向上取整的转换方法
|
||||
我们知道,一般在程序语言中,两个整数相除都是向下取整。例如,$5/3=1,2/3=0$;
|
||||
|
||||
那么向上取整该如何表示呢,也就是说,**向上取整能不能通过向下取整的方式来表达**?
|
||||
|
||||
当然可以,下面是转换公式:
|
||||
<center><img src='https://img-blog.csdn.net/20140113090723046'></center>
|
||||
Reference in New Issue
Block a user