网站建设找北冥有鱼成都微信公司地址在哪里
文章目录
- 简介
 - AcWing 890. 能被整除的数
 - 思路解析
 - CODE
 
简介
推荐题解:https://www.acwing.com/solution/content/126553/
 画了图,清晰易懂,懒得打字了。
 总之就是以下公式: S = S 1 + S 2 + S 3 − S 1 ∩ S 2 − S 1 ∩ S 3 − S 2 ∩ S 3 + S 1 ∩ S 2 ∩ S 3 \begin{align*} S = & S_1 + S_2 + S_3 \\ & - S_1 \cap S_2 - S_1 \cap S_3 - S_2 \cap S_3 \\ & + S_1 \cap S_2 \cap S_3 \end{align*} S=S1+S2+S3−S1∩S2−S1∩S3−S2∩S3+S1∩S2∩S3
 我们可以把这个式子推导到  n n n 维,奇加偶减。
AcWing 890. 能被整除的数
题目链接:https://www.acwing.com/activity/content/problem/content/960/
 
思路解析
筛出一个数的倍数,两个数的倍数 … n n n 个数的倍数,这就抽象成了 n n n 个集合的问题了。
那么如何表示选取哪几个集合(质数)呢?
- 从 1 1 1 开始枚举到 n n n,将每个数看成二进制形式,如果说第 k k k 位是 1 1 1,那么就代表选第 k k k 个集合,反之不选。
 
如何知道被整除的数的个数?公式: n / p n / p n/p 下取整即可。
最后判断是奇数个还是偶数个,这个判断利用了二进制的一个性质:除了 2 0 2^0 20,其他所有位的和都是 2 2 2 的整数倍,所以说看是否为奇数就看它二进制最后一位是否为 1 1 1。
CODE
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;typedef long long ll;  // 定义长整型别名为llconst int N = 20;  // 定义常量N为20
int n, m;  // 定义整型变量n和m
int p[N];  // 定义整型数组p,大小为Nint main(){scanf("%d%d", &n, &m);  	// 从输入中读取两个整数n和mfor(int i = 0; i < m; ++i) scanf("%d", &p[i]);  // 从输入中读取m个整数到数组p中int res = 0;  	// 初始化结果为0for(int i = 1; i < (1 << m); ++i){  // 遍历所有的子集int s = 0, t = 1;  	// 初始化s和tfor(int j = 0; j < m; ++j){  	// 遍历每一位if(i >> j & 1){  	// 如果第j位为1if((ll)t * p[j] > n){  	// 如果t乘以p[j]大于nt = -1;  	// 将t设置为-1break;  	// 跳出循环}t *= p[j];  // 更新ts++;  // 增加s}}if(t == -1) continue;  	// 如果t为-1,跳过当前循环if(s & 1) res += n / t;  // 如果s为奇数,增加n/t到reselse res -= n / t;  	// 否则,从res中减去n/t}cout << res << endl;  // 输出结果
}