容斥原理:能被整除的数

简介: 容斥原理:能被整除的数

给定一个整数 n和 m个不同的质数 p1,p2,…,pm。


请你求出 1∼n中能被 p1,p2,…,pm中的至少一个数整除的整数有多少个。


输入格式

第一行包含整数 n和 m。


第二行包含 m个质数。


输出格式

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


数据范围

1≤m≤16,

1≤n,pi≤10^9


输入样例:
1. 10 2
2. 2 3
输出样例:
7

容斥原理定义:在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。


思路:用遍历模运算在数据量小的时候是常用的算法,但是本题n为10^9,复杂度过高会TLE。


这里使用容斥原理,不计算出每个符合情况的数有哪些,仅去计算个数有多少,这样就降低了时间复杂度。


p[N]存放质数,假设pi指可以被p[i]整除的个数,那么pi=n/p[i];


类推pi并上pj   pi||pj=n/pi*pj;利用容斥原理就可以计算出p1p2p3....pn的个数,qie时间复杂度为2^m

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=16;
int n,m,p[N];
ll res;
int main(){
    cin>>n>>m;
    for(int  i=0;i<m;i++)cin>>p[i];
    for(int i=1;i<1<<m;i++)
    {
        int t=1,cnt=0;
        for(int  j=0;j<m;j++)
        {
            if(i>>j&1)
            {
                cnt++;
                if((ll)t*p[j]>n)
                {
                    t=-1;
                    break;
                }
                t*=p[j];
            }
        }
        if(t!=-1)
        {
            if(cnt%2)res+=n/t;
            else res-=n/t;
        }    
    }
    cout<<res<<endl;
    return 0;
}
相关文章
|
6月前
|
BI 测试技术 Windows
【数位】【数论】【分类讨论】2999. 统计强大整数的数目
【数位】【数论】【分类讨论】2999. 统计强大整数的数目
|
16天前
求一个整数的所有因数
【10月更文挑战第25天】求一个整数的所有因数。
13 5
|
19天前
求这两个数的最大公约数
【10月更文挑战第21天】求这两个数的最大公约数。
8 1
|
6月前
26.一个正整数如果恰好等于它的因子之和,这个数称为“完数”,如6=1+2+3,求1000以内所有的完数.
26.一个正整数如果恰好等于它的因子之和,这个数称为“完数”,如6=1+2+3,求1000以内所有的完数.
65 0
|
6月前
|
算法 测试技术 C#
【最大公约数 调和级数】2183.统计可以被 K 整除的下标对数目
【最大公约数 调和级数】2183.统计可以被 K 整除的下标对数目
求一个数是几位数并输出逆序数
求一个数是几位数并输出逆序数
63 0
|
12月前
628. 三个数的最大乘积
628. 三个数的最大乘积
|
Python
找几个数的最大乘积
找几个数的最大乘积
72 0
|
索引
三个数的最大乘积
三个数的最大乘积
68 0
|
机器学习/深度学习 人工智能 算法
能被整除的数
能被整除的数
能被整除的数