【ACWing】890. 能被整除的数

题目地址:

https://www.acwing.com/problem/content/892/

给定一个整数 n n n m m m个不同的素数 p 1 , . . . , p m p_1,...,p_m p1,...,pm,求 1 ∼ n 1\sim n 1n中能被 p 1 , . . . , p m p_1,...,p_m p1,...,pm之一整除的整数有多少个。

输入格式:
第一行包含整数 n n n m m m。第二行包含 m m m个质数。

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

数据范围:
1 ≤ m ≤ 16 1\le m\le 16 1m16
1 ≤ n , p i ≤ 1 0 9 1\le n,p_i\le 10^9 1n,pi109

可以用容斥原理。设 S i = { 1 ≤ k ≤ n : p i ∣ n } S_i=\{1\le k\le n:p_i|n\} Si={1kn:pin},由容斥原理知道,答案是: ∑ i = 1 m ∣ S i ∣ − ∑ i 1 < i 2 ∣ S i 1 ∩ S i 2 ∣ + ∑ i 1 < i 2 < i 3 ∣ S i 1 ∩ S i 2 ∩ S i 3 ∣ − . . . + ( − 1 ) m − 1 ∣ S 1 ∩ S 2 ∩ . . . ∩ S m ∣ \sum_{i=1}^{m} |S_i|-\sum_{i_1<i_2} |S_{i_1}\cap S_{i _2}|+\sum_{i_1<i_2<i_3} |S_{i_1}\cap S_{i _2}\cap S_{i_3}|-...+(-1)^{m-1} |S_1\cap S_2\cap...\cap S_m| i=1mSii1<i2Si1Si2+i1<i2<i3Si1Si2Si3...+(1)m1S1S2...Sm我们只需算出每个 1 ∼ n 1\sim n 1n中被 p i p_i pi整除的数的个数,这个个数就是 ⌊ n p i ⌋ \lfloor \frac{n}{p_i}\rfloor pin。因为 m ≤ 16 m\le 16 m16,可以用二进制枚举的方式来枚举所有取哪些素数的情况,即某个数 x x x的右起第 i i i个二进制位(这里从 1 1 1开始计数)是 1 1 1就表示第 p i p_i pi是取的。代码如下:

#include <iostream>
using namespace std;

const int N = 20;
int n, m;
// 存所有的素数
int p[N];

int main() {
  cin >> n >> m;
  for (int i = 0; i < m; i++) cin >> p[i];

  int res = 0;
  // 枚举所有的素数取法(只有什么都不取这个取法是不枚举的)
  for (int i = 1; i < 1 << m; i++) {
    // prod存当前取法的素数乘积,cnt存当前取法的素数个数
    int prod = 1, cnt = 0;
    // 看一下第j + 1个素数是否取了
    for (int j = 0; j < m; j++)
      if (i >> j & 1) {
        cnt++;
        // 如果当前取法的素数乘积大于n了,那这个乘积无法作为因子,直接退出循环
        if ((long) prod * p[j] > n) {
          prod = -1;
          break;
        }
        prod *= p[j];
      }

      if (prod != -1) 
        if (cnt % 2) res += n / prod;
        else res -= n / prod;
  }

  cout << res << endl;
}

时间复杂度 O ( 2 m m ) O(2^mm) O(2mm),空间 O ( 1 ) O(1) O(1)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值