输入1个数N(1 <= N <= 10^18)。
输出不是2 3 5 7的倍数的数共有多少。
10
1
时间超限:
#include <iostream>using namespace std;
int main()
{
long long i,n,sum;
cin>>n;
sum=n;
for(i=1;i<=n;i++)
{
if(i%2==0 || i%3==0 || i%5==0 || i%7==0)
sum--;
}
cout<<sum;
return 0;
}
AC:
#include <iostream>using namespace std;
typedef long long ll;
int main(){
//离散数学里面的知识,利用容斥原理(4个集合:A1:2的倍数,A:3的倍数,A3:5的倍数,A4 :7的倍数)
ll a; //A1+A2+A3+A4
ll b; //A1A2+A1A3+A1A4+A2A3+A2A4+A3A4
ll c; //A1A2A3+A1A2A4+A1A3A4+A2A3A4
ll d; //A1A2A3A4
ll n,sum,ans;
while(cin>>n)
{
a=n/2+n/3+n/5+n/7; //表示是2 3 5 7 的倍数的数个数,里面包含重复计算
b=n/6+n/10+n/14+n/15+n/21+n/35; //任意两个结合的所有可能情况,里面包含3个集合相交和4个集合相交
c=n/30+n/42+n/70+n/105; //表示示三个集合相交的情况,包含四个集合相交的情况
d=n/210; //表示四个集合相交
//sum为满足 是2.3.5.7其中一个或多个的倍数 的数;
sum=a-b+c-d;
ans=n-sum;
cout<<ans<<endl;
}
return 0;
}
AC(便于理解)
#include <iostream>
using namespace std;
int main()
{
long long n,num,a,b,c,d,ab,ac,ad,bc,bd,cd,abc,abd,bcd,acd,abcd;
cin>>n;
num=0;
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;
cout<<n-num<<endl;
return 0;
}
---------------------
容斥原理:
在计数时,必须注意没有重复,没有遗漏。
为了使重叠部分不被重复计算,人们研究出一种新的计数方法,
这种方法的基本思想是:先不考虑重叠的情况, 把包含于某内容中的所有对象的数目先计算出来,
然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,
这种计数的方法称为容斥原理。
要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个集合相交的部分,
再加回所有三个集合相交的部分,再减去所有四个集合相交的部分,依此类推,一直计算到所有集合相交的部分。
两个集合的容斥关系公式:A∪B = A+B - A∩B (∩:重合的部分)
三个集合的容斥关系公式:A∪B∪C = A+B+C - A∩B - B∩C - C∩A +A∩B∩C
四个有限集合 :A∪B∪C∪D=A+B+C+D- A∩B - B∩C - C∩A- A∩D - B∩D - C∩D+A∩B∩C+A∩B∩D +A∩C∩D +B∩C∩D -A∩B∩C∩D