前言:
溫馨提示,此篇博客將涉及排列組合(鏈接)。
概念:
在計數時,必須注意沒有重複,沒有遺漏。爲了使重疊部分不被重複計算,人們研究出一種新的計數方法,這種方法的基本思想是:先不考慮重疊的情況,把包含於某內容中的所有對象的數目先計算出來,然後再把計數時重複計算的數目排斥出去,使得計算的結果既無遺漏又無重複,這種計數的方法稱爲容斥原理。
好了,我們理解概念,開始例題吧。
例題一:
描述:
一年級某班有30人,考了語文和數學,語文上90的有17人,數學上90的有25人,語文和數學同時上90的有15人。問有多少同學兩門課都沒有上90?
答案:
3人。
分析:
如圖,上了語文90分的人和上了語文90分的人的和重複了語文和數學同時上的人,所以是:30-17-25+15=3人。
例題二:
描述:
假設班裏有50名學生,每個人都必須選修一門運動科目,選修籃球的有15人,選修足球的有20人,選修乒乓球的有30人,同時選修籃球和足球的有10人,同時選修乒乓球和足球的有18人,同時選修籃球和乒乓球的有12人,問選修了三門科目的有多少人?
答案:
無解。
分析:
WHAT?!!你的心裏一定是這樣想的。
別急我們分析一下:
選修籃球的加選修足球的加選修乒乓球的減去同時選修籃球和足球的和同時選修乒乓球和足球的與同時選修籃球和乒乓球的就是
班裏人數減去三門都選修了的。
所以應是25人。
可是,選修籃球的就只有15人,那麼多的10人從何而來呢?
所以無解。
例題三:
描述:
你是一個喜歡編程的手機經銷商,一次你得到了一個邊長爲n的正方體箱子,裏面裝滿了長,寬,高爲a,b,c的華爲手機盒,手機盒均朝同一方向擺放。這時,一束陽光正好照過正方體箱子的對角線,你想知道,這一束陽光穿過了多少手機盒。
(n<=100000,a,b,c均爲n的約數)。
輸入:
輸入4個正整數,分別表示n,a,b,c。
輸出:
輸出光束穿過手機盒的數量。
輸入樣例:
10 5 2 2
輸出樣例:
6
思路分析:
我們先從二維平面開始講,因爲從對角線穿過,所以它只會穿過上底和右高(從左上到右下)。
那麼穿過長的條數爲n/a,寬的條數爲n/b,但是會穿過頂點,而它又被加了兩次,所以減去n/lcm( a , b)。
來到三維也是這個操作。
就是:n/a+n/b+n/c-n/lcm(a,b)-n/lcm(b,c)-n/lcm(a,c)+n/lcm(lcm(b,c),a))。
代碼實現:
#include<cstdio>
#include<iostream>
#include<algorithm>
long long n,a,b,c;
long long gcd(long long x,long long y)
{
if(!y)
return x;
else
{
r=gcd(y,x%y);
return r;
}
}
long long lcm(long long x,long long y)
{
return x*y/gcd(x,y);
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
printf("%lld",n/a+n/b+n/c-n/lcm(a,b)-n/lcm(b,c)-n/lcm(a,c)+n/lcm(lcm(b,c),a));
}