要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个集合相交的部分,再加回所有三个集合相交的部分,再减去所有四个集合相交的部分,依此类推,一直计算到所有集合相交的部分。
简单来说,就是奇加偶减。
举个例子:
求1~n中多少个数不是2,3,5,7的倍数,当n=10,结果只有1一个数。
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int ans=n-(n/2+n/3+n/5+n/7)+(n/2/3+n/2/5+n/2/7+n/3/5+n/3/7+n/5/7)-(n/2/3/5+n/2/3/7+n/3/5/7+n/2/5/7)+n/2/3/5/7;
//ans=n-(n/2+n/3+n/5+n/7)+(n/6+n/10+n/14+n/15+n/21+n/35)-(n/30+n/42+n/105+n/70)+n/210
cout<<ans<<endl;
return 0;
}
例子2:
题目描述:
V_Dragon有n盏电灯泡,编号为1-n,每个灯泡都有一个开关,那么问题来了
- 所有灯泡初始时为不亮的;
- V_Dragon分别进行三次操作;
- 每次操作他都选一个质数x,将编号为x和x的整数倍的灯泡的开关都拨动一下(如果灯为亮,那么拨动以后灯为不亮,如果灯不亮,拨动以后变为亮)
求最后亮着的灯的数量;
输入:
输入T表示T组测试数据(1<=T<=100)
接下来T组数据
每组第一行一个n表示灯泡各数(1<=n<=109)
第二行三个数a,b,c表示V_Dragon每次选择的数(1<=a,b,c<=106)(a,b,c全为质数且a,b,c两两互不相等)
输出:
最后亮着的灯的个数
样例输入:
1
30
2 3 5
样例输出:
15
题解:
原来的方法:
a+b+c-(ab+ac+bc)+abc。这祥的话a+b+c代表的是啊a,b,c总的要按的灯的按钮。
而ab,bc,ac代表的是按两次或者两次以上灯的数量。
这里我们应该想一下,如果只是减一个ab+ac+bc的话,那就是三次所涉及的总共灯的数量,
但是对一个灯操作两次,灯就关了。这祥就不需要计算这一块了。所以应该减两次ab+ac+bc。
再看+abc。我们将在前面已经-2*(ab+bc+ac)了,就相当于将abc这一块减了三次,
但是对于abc这一块,三次操作还是亮着的。所以应该加上4*(abc)。
所以最后的公式应该是a+b+c-2(ab+bc+ac)+4abc.
#include<iostream>
using namespace std;
int main()
{
int T,n,a,b,c;
cin>>T;
while(T--)
{
cin>>n;
cin>>a>>b>>c;
int sum=n/a+n/b+n/c-2*(n/a/b+n/b/c+n/a/c)+4*(n/a/b/c);
//int sum= n/a+n/b+n/c-2*( n/(a*b) + n/(b*c) + n/(a*c) )+4*( n/(a*b*c) )
//这里 其实应该是n*gcd(a,b)/(a*b)...但是因为题目中说a,b,c互质,所以gcd=1,但是如果题目中不说互质,就需要乘以gcd
cout<<sum<<endl;
}
return 0;
}