数学-能被整除的数-容斥定理

c++

AcWing 890. 能被整除的数

/*
* 问题描述:
* AcWing 890. 能被整除的数
* 给定一个整数 n 和 m 个不同的质数 p1,p2,…,pm。
* 请你求出 1∼n 中能被 p1,p2,…,pm 中的至少一个数整除的整数有多少个。
* 输入格式
* 第一行包含整数 n 和 m。
* 第二行包含 m 个质数。
* 输出格式
* 输出一个整数,表示满足条件的整数的个数。
* 数据范围
* 1 ≤ m ≤ 16,
* 1 ≤ n, pi ≤ 10 ^ 9
*
* 解题思路:
* 容斥定理:
* |A1 \cup A2 \cup ... \cup An| = |A1| + |A2| + ... + |An|
* - sum_{i, j}(|Ai \cap Aj|)
* + sum_{i, j, k}(|Ai \cap Aj \cap Ak|)
* ...
* 证明思路可以从 a1, a2, ..., ai 几个集合相交的情况下,查看上个公式的计数是否为 1 :
* C(i, 1) - C(i, 2) + ... + C(i, j) * (-1) ^ (j + 1) + ... + C(i, i) * (-1) ^ (i + 1)
* 从 (1 + x) ^ i = 1 + C(i, 1) * x + ... + C(i, j) * x ^ j + ... + C(i, i) * x ^ i
* 取 x = -1
* 可得 C(i, 1) + ... + C(i, j) * (-1) ^ (j + 1) + ... + C(i, i) * (-1) ^ (i + 1) = 1
* 就是说任意几个集合的结合,计数为 1,该定理计数是正确的。
*
* 带入到本题,直接使用状态循环,又因为互质,免得求解最大公因数了。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int n, m;
int p[25];
LL solution() {
LL res = 0;
int cnt = 0;
int cur = n;
for (int state = 1; state < (1 << m); state ++ ) {
cnt = 0;
cur = n;
for (int i = 0; i < m; i ++ ) {
if ((state >> i) & 1) {
cnt += 1;
cur /= p[i + 1];
}
}
if (cnt % 2 == 1) {
res += cur;
} else {
res -= cur;
}
}
return res;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++ ) {
scanf("%d", &p[i]);
}
LL res = solution();
printf("%lld", res);
return 0;
}
posted @   lucky_light  阅读(179)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示