「學習筆記」容斥原理及其應用
阿新 • • 發佈:2018-11-11
容斥原理
說的是一種計數方式,使得每種情況只被記一次。
入門例題
錯排問題模板題。
推一下遞推式子:
把 個 當成 個條件然後容斥,每次選一些不錯位,剩下隨便排.
#include <cstdio>
long long dp[21];
int main() {
dp[0] = dp[1] = 0;
for(int i = 2; i <= 20; i ++)
dp[i] = i * 1ll * dp[i - 1] + ((i & 1) ? -1 : 1);
for(int n; ~ scanf("%d", &n); )
printf("%lld\n", dp[n]);
return 0;
}
題意:給定 個數 ,求小於 的數中有多個數滿足能被任意一個 整除.
容斥應用入門題。 容斥一下就好。即加上只被某1個整除的,減去被某2個整除的,加上…
#include <cstdio>
typedef long long LL;
int n, m, a[10];
LL ans;
LL gcd(const LL & a, const LL & b) {
return b == 0 ? a : gcd(b, a % b);
}
LL lcm(const LL & a, const LL & b) {
return a / gcd(a, b) * b;
}
void dfs(int k, int c, LL ret) {
if(k == m) {
if(c > 0) ans += ((n - 1) / ret) * ((c & 1) ? 1 : -1);
return ;
}
dfs(k + 1, c, ret);
if(a[k] > 0 && a[k] < n)
dfs(k + 1, c + 1, lcm(ret, a[k]));
}
int main() {
while(~ scanf("%d%d", &n, &m)) {
for(int i = 0; i < m; i ++)
scanf("%d", &a[i]);
ans = 0;
dfs(0, 0, 1);
printf("%lld\n", ans);
}
return 0;
}
題意:求 中與 互質的數, .
首先拆成字首,轉換為求 中與 互質的數。
這個不好求,補集轉化,求為求 中與 不互質的數,然後用 減去這個答案。
不互質意味著包含 的某個質因子,把 質因數分解為