给出一个数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
解题思路:
先分别求有多少是2、3、5、7的倍数,设分别有a、b、c、d个。
然后分别求有多少是6(2和3最小公倍数)、10(2和5最小公倍数)、14(2和7最小公倍数)、
15(3和5最小公倍数)、21(3和7最小公倍数)、
35(5和7)最小公倍数的倍数,设分别有e、f、g、h、i、j个。
再分别求有多少是30(2、3、5最小公倍数)、
42(2、3、7最小公倍数)、70(2、5、7最小公倍数)、
105(3、5、7最小公倍数)的倍数,设分别有k、l、m、q个。
再求有多少是210(2、3、5、7最小公倍数)的倍数,设有o个,
最后,不是2、3、5、7的倍数的数字有:
[n-(a+b+c+d)+(e+f+g+h+i+j)-(k+l+m+q)+o]个
ac代码(1)
#include <iostream>
#include<stdio.h>
using namespace std;
long long n,num,a,b,c,d,ab,ac,ad,bc,bd,cd,abc,abd,bcd,acd,abcd;
int main()
{
scanf("%lld",&n);
a=n/2;
b=n/3;
c=n/5;
d=n/7;
ab=n/6;
ac=n/10;
ad=n/14;
bc=n/15;
bd=n/21;
cd=n/35;
abc=n/30;
abd=n/42;
acd=n/70;
bcd=n/105;
abcd=n/210;
num=a+b+c+d-ab-ac-ad-bc-bd-cd+abc+abd+acd+bcd-abcd;
printf("%lld\n",n-sum);
return 0;
}
这样写需要定义太多变量,下面给出改进。
思路和上面思路一样,只不过把式子综合起来。
l令 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;
最终结果为:
[n-(a-b+c-d)]=[n-a+b-c+d];
ac代码(2)
#include<stdio.h>
using namespace std;
int main()
{
long long n,num,a,b,c,d;
scanf("%d",&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;
num=a-b+c-d;
printf("%lld\n",n-num);
return 0;
}
本题应用了容斥原理。
要计算几个集合并集的大小,我们要先将单个集合的大小计算出来,然后减去两个集合相交的部分,再加回三个集合相交的部分,再减去四个集合相交的部分,以此类推,一直计算到所有集合相交的部分。
那么的面积就是集合A、B、C各自面积之和减去 , , 的面积,再加上的面积。
由此,我们也可以解决n个集合求并的问题。