对于三个圆, S1,S2,S3他们如上图所示,现在要求求他们所构成图形的面积,该如何去求?
这个问题很简单,
S
=
S
1
+
S
2
+
S
3
−
(
S
1
∩
S
2
)
−
(
S
1
∩
S
3
)
−
(
S
2
∩
S
3
)
+
(
S
1
∩
S
2
∩
S
3
)
S = S_1 + S_2 + S_3 - (S_1\cap S_2) - (S_1 \cap S_3) - (S_2 \cap S_3) + (S_1 \cap S_2 \cap S_3)
S=S1+S2+S3−(S1∩S2)−(S1∩S3)−(S2∩S3)+(S1∩S2∩S3)
如果换成四个呢?
经过猜想推广可以猜到四个的话就是
S
=
C
4
1
S
?
−
C
4
2
(
S
?
∩
S
?
?
)
+
C
4
3
(
S
?
∩
S
?
?
∩
S
?
?
?
)
−
C
4
4
(
S
?
∩
S
?
?
∩
S
?
?
?
∩
S
?
?
?
?
)
S = C_4^1S_? - C_4^2(S_? \cap S_{??}) + C_4 ^3 (S_? \cap S_{??} \cap S_{???}) - C_4^4(S_? \cap S_{??} \cap S_{???} \cap S_{????})
S=C41S?−C42(S?∩S??)+C43(S?∩S??∩S???)−C44(S?∩S??∩S???∩S????)
其实用话来描述就是,
C
4
1
C_4^1
C41个单个的面积 -
C
4
2
C_4^2
C42两个相交的面积…很好理解
对于这样的计算,可以发现有正负之分,当组合数上选择的的数是奇数时该项为正,否则为负。
能被整除的数
思路:
把每个质数能整除的数都看成集合,之间相互有交集,现在其实要求的就是并集
对于1 - n之间的数,能被质数
m
1
m_1
m1整除的有
n
m
1
\frac{n}{m_1}
m1n个,能被
m
1
∗
m
2
m_1 * m_2
m1∗m2整除的有
n
m
1
∗
m
2
\frac{n}{m_1*m_2}
m1∗m2n个。
对于每个质数,枚举所有的组合,都可以看做选或者不选,很自然就可以想到二进制枚举,复杂度即 O ( m 2 ) O(m^2) O(m2)
#include<bits/stdc++.h>
#define ll long long
#define eps 1e-8
#define INF 0x3f3f3f3f
#define pb push_back
#define endl '\n'
#define IO ios::sync_with_stdio(false)
using namespace std;
const ll N = 21,M = 1 << N;
const ll mod = 1e9 + 7;
int n,m,p[25];
ll ans = 0;
int main(){
cin >> n >> m;
for(int i = 0; i < m; i++)
cin >> p[i];
for(int i = 1; i < (1 << m); i++){//二进制枚举
ll t = 1,cnt = 0;
for(int j = 0; j < m; j++){
if((i >> j) & 1){
cnt++;//统计选取的个数
if(t * p[j] > n){//如果比n大则不合法
t = -1;
break;
}
t *= p[j];
}
}
if(t != -1){//根据选取的个数进行计算
if(cnt % 2)ans += n / t;
else ans -= n / t;
}
}
cout << ans << endl;
return 0;
}
牛牛的棋盘
思路:
首先,考虑从n * m个格子中挑k个格子放棋子,即
C
n
∗
m
k
C_{n*m}^k
Cn∗mk种。
然后减去不符合条件的即,减去周围没有放棋子的情况,比如顶端没放有
C
(
n
−
1
)
∗
m
k
C_{(n - 1) * m}^k
C(n−1)∗mk种,如此类推,可以发现就是一个容斥定理
typedef long long ll;
const ll mod = 1e9 + 7;
ll inv[1005], fec[1005];
class Solution {
public:
ll qpow(ll a,ll b){
ll res = 1;
while(b){
if(b&1)res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
void init(){
fec[0] = 1;
for(int i = 1; i <= 1000; i++)
fec[i] = fec[i - 1] * i % mod;
inv[1000] = qpow(fec[1000], mod - 2);
for(int i = 999; i >= 0; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll C(ll n,ll m){
return fec[n] * inv[n - m] % mod * inv[m] % mod;
}
int solve(int n, int m, int k) {
init();
int ans = 0;
for(int i = 0,N ,M,cnt; i < (1 << 4); i++){
N = n,M = m,cnt = 0;
for(int j = 0; j < 4; j++){
if((i >> j) & 1){
if(j & 1)N--;
else M--;
cnt++;
}
}
if(N * M < k)continue;
if(cnt&1)ans = ans - C(N * M, k);
else ans = ans + C(N * M, k);
}
return (ans % mod + mod) % mod;
}
};