跳到主要内容

容斥原理

AcWing 890. 能被整除的数

给定一个整数 nnmm 个不同的质数 p1,p2,,pmp_1, p_2, …, p_m

请你求出 1n1 \sim n 中能被 p1,p2,,pmp_1, p_2, …, p_m 中的至少一个数整除的整数有多少个。

输入格式

第一行包含整数 nnmm

第二行包含 mm 个质数。

输出格式

输出一个整数,表示满足条件的整数的个数。

数据范围

1m161 \le m \le 16,
1n,pi1091 \le n,p_i \le 10^9

输入样例:

10 2
2 3

输出样例:

7

思路

image-20230801185110729

使用二进制位来表示每个集合选与不选,集合计算答案的时候正负交错进行,即选奇数个为加,选偶数个为减

image-20230801185004547

代码

/**
* https://www.acwing.com/problem/content/892/
*/
#include <bits/stdc++.h>

#define int long long
using namespace std;


signed main() {
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
int n, m;
cin >> n >> m;
int ans = 0;
vector<int> p(m);
for (int i = 0; i < m; ++i) cin >> p[i];
for (int i = 1; i < (1 << m); i++) {
int t = 1, sign = -1;
for (int j = 0; j < m; j++) {
if (i >> j & 1) {
t *= p[j];
if (t > n) {
t = 0;
break;
}
sign = -sign;
}
}
if (t)ans += sign * (n / t);
}
cout << ans << endl;
return 0;
}

Indivisibility

题面翻译

题目描述

开发电脑游戏的IT City公司,准备改善员工奖励机制。奖励机制是这样的,当游戏的注册用户开始花钱购买产品时,公司会精确的跟踪每笔交易。每次当交易次数不能被2~10之间的任何数字整除时,这个游戏的每个开发者都会得到一个小奖励。

游戏设计师Petya知道公司即将发布一款由他开发的新游戏。根据他的经验,他预测第一个月将会有n个人购买这个游戏。现在Petya想知道他能够获得多少次奖励?

输入格式

一行,一个整数n(1≤n≤10^18),表示购买游戏的人的个数

输出格式

一行,表示1n中不能被210中任意一个数整除的数的数量

感谢@zhangyuhan 提供翻译

题目描述

IT City company developing computer games decided to upgrade its way to reward its employees. Now it looks the following way. After a new game release users start buying it actively, and the company tracks the number of sales with precision to each transaction. Every time when the next number of sales is not divisible by any number from 22 to 1010 every developer of this game gets a small bonus.

A game designer Petya knows that the company is just about to release a new game that was partly developed by him. On the basis of his experience he predicts that nn people will buy the game during the first month. Now Petya wants to determine how many times he will get the bonus. Help him to know it.

输入格式

The only line of the input contains one integer nn ( 1<=n<=10181<=n<=10^{18} ) — the prediction on the number of people who will buy the game.

输出格式

Output one integer showing how many numbers from 11 to nn are not divisible by any number from 22 to 1010 .

样例输入 #1

12

样例输出 #1

2

思路

和上面一题一样,利用容斥原理,这里只需要把p数组换成2~10即可。

代码

#include <bits/stdc++.h>

#define int long long
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
#define IOS cin.tie(0), cout.tie(0), ios::sync_with_stdio(false);
#define cxk 1
#define debug(s, x) if (cxk) cout << "#debug:(" << s << ")=" << x << endl;
using namespace std;

int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}

int lcm(int a, int b) {
return a * b / gcd(a, b);
}

void solve() {
int n;
cin >> n;
int res = 0;
vector<int> a;
for (int i = 2; i <= 10; i++) a.push_back(i);
for (int i = 1; i < (1 << 9); i++) {
int t = 1, sign = -1;
for (int j = 0; j < 9; j++) {
if (i >> j & 1) {
t = lcm(t, a[j]);
sign *= -1;
}
}
res += sign * (n / t);
}
cout << n - res << endl;
}

signed main() {
IOS
#ifndef ONLINE_JUDGE
freopen("../test.in", "r", stdin);
freopen("../test.out", "w", stdout);
#endif
int _ = 1;
while (_--) solve();
return 0;
}