51nod-1284 2 3 5 7的倍数 (容斥原理)

来源:互联网 发布:淘宝怎么上架莆田鞋 编辑:程序博客网 时间:2024/05/25 12:22

给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数。 例如N = 10,只有1不是2 3 5 7的倍数。
Input
输入1个数N(1 <= N <= 10^18)。
Output
输出不是2 3 5 7的倍数的数共有多少。
Input示例
10
Output示例
1
容斥原理:
在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。
     如果被计数的事物有A、B、C三类,那么,A类和B类和C类元素个数总和= A类元素个数+ B类元素个数+C类元素个数—既是A类又是B类的元素个数—既是A类又是C类的元素个数—既是B类又是C类的元素个数+既是A类又是B类而且是C类的元素个数。(A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C)


上面是百度上的知识,说白了就是要计算几个集合并集的大小,我们要先将单个集合的大小计算出来,然后减去两个集合相交的部分,再加回三个集合相交的部分,再减去四个集合相交的部分,以此类推,一直计算到所有集合相交的部分。(1-2+3-4-5+6-7+8*******)
所以这个题目要求的是不是2 3 5 7的倍数,可以求是2 3 5 7的倍数之后,再减去即可。这样就会用到容斥原理,先求仅仅只是整除2 3 5 7的数量,再减去整除了它们之间两两的乘积的数量,再加上整除它们三个之间的乘积的数量,再加上整除四个的数量。

特别注意·:要用long long型
#include <stdio.h>#include <string.h>typedef long long ll;int main(){    ll a;    ll b;    ll c;    ll d;    ll n,sum;    while(~scanf("%lld",&n))    {        a=n/2+n/3+n/5+n/7;        b=n/6+n/10+n/14+n/15+n/21+n/35;        c=n/30+n/42+n/70+n/105;        d=n/210;        ll t=a-b+c-d;//2 3 5 7 的倍数个数,容斥原理        sum=n-t;        printf("%lld\n",sum);    }    return 0;}