1. 程式人生 > >「學習筆記」容斥原理及其應用

「學習筆記」容斥原理及其應用

容斥原理

說的是一種計數方式,使得每種情況只被記一次。

i = 1 n C

n i ( 1 ) i + 1
= [ n 1 ] \sum_{i=1}^{n}C_n^i(-1)^{i+1}=[n\geq 1]

入門例題

(1) HDU 1465 \text{(1) HDU 1465}

錯排問題模板題。

推一下遞推式子:

n n i ̸ = a i i\not = a_i 當成 n n 個條件然後容斥,每次選一些不錯位,剩下隨便排.

d p [ n ] = i = 0 n ( 1 ) i + 1 C n i ( n i ) ! dp[n]=\sum_{i=0}^n (-1)^{i+1}C_{n}^{i}(n-i)!

d p [ n ] = i = 0 n ( 1 ) i + 1 n ! i ! ( n i ) ! ( n i ) ! dp[n]=\sum_{i=0}^n (-1)^{i+1}\frac{n!}{i!(n-i)!}(n-i)!

d p [ n ] = i = 0 n ( 1 ) i + 1 n ! i ! dp[n]=\sum_{i=0}^n (-1)^{i+1}\frac{n!}{i!}

d p [ n ] = ( 1 ) n + i = 0 n 1 ( 1 ) i + 1 n ! i ! dp[n]=(-1)^n+\sum_{i=0}^{n-1} (-1)^{i+1}\frac{n!}{i!}

d p [ n ] = ( 1 ) n + n i = 0 n 1 ( 1 ) i + 1 ( n 1 ) ! i ! dp[n]=(-1)^n+n\sum_{i=0}^{n-1} (-1)^{i+1}\frac{(n-1)!}{i!}

d p [ n ] = ( 1 ) n + n    d p [ n 1 ] dp[n]=(-1)^n+n \;dp[n-1]

#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;
}

(2) HDU 1796 \text{(2) HDU 1796}

題意:給定 m ( m 10 ) m(m\leq 10) 個數 a i a_i ,求小於 n n 的數中有多個數滿足能被任意一個 a i a_i 整除.

容斥應用入門題。 DFS \text{DFS} 容斥一下就好。即加上只被某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;
}

(3) HDU 4135 \text{(3) HDU 4135}

題意:求 [ a , b ] [a,b] 中與 n n 互質的數, a , b 1 0 15 , n 1 0 9 a,b \leq 10^{15},n\leq 10^9 .

首先拆成字首,轉換為求 [ 1 , r ] [1,r] 中與 n n 互質的數。

這個不好求,補集轉化,求為求 [ 1 , r ] [1,r] 中與 n n 不互質的數,然後用 r r 減去這個答案。

不互質意味著包含 n n 的某個質因子,把 n n 質因數分解為 i = 1 k