1. 程式人生 > 其它 >SpringBoot: 後臺介面文件 - 基於Swagger3

SpringBoot: 後臺介面文件 - 基於Swagger3

是一個很經典集合問題。
在一個點集中,一定可以分割成若干個聯通子集。
如果我們設 \(f_i\) 為一個點集的聯通方案,\(g_i\) 為一個點集的所有方案。
我們先任取一個點,考慮列舉一個集合和這個點不聯通。
那麼我們知道這樣不連通的方案 \(\sum g[j] \times\ f[i\ xor\ j]\)
依據簡單的容斥:
\(f_i = g_i - \sum_{s\in(i\ xor\ j)}\ g[j] \times\ f[i\ xor\ j]\)
答案為 \(f_{2^n - 1}\)

在實現有細節,即先把當前集合丟掉 \(lowbit(i)\),在列舉不連通的子集。

#include<iostream>
#include<cstdio>
#define ll long long 
#define mod 1000000007
#define N 20
#define M (1 << 17)

ll n;

ll c[N][N];

ll f[M],g[M];

int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i)
	for(int j = 1;j <= n;++j)
	scanf("%lld",&c[i - 1][j - 1]);
	ll K = (1 << n) - 1;
	for(int i = 0;i <= K;++i){
		g[i] = 1;
		for(int j = 0;j <= n - 1;++j){
			for(int k = j + 1;k <= n - 1;++k){
				if(((i >> j) & 1) && ((i >> k) & 1))
				g[i] = (g[i] * (c[j][k] + 1)) % mod;
			}
		}
	}
	for(int i = 0;i <= K;++i){
		f[i] = g[i];
		int t = i ^ (i & -i);
		for(int j = t;j > 0;j = (j - 1) & t){
			f[i] = (f[i] - g[j] * f[i ^ j] % mod + mod) % mod;
		}
	}
	std::cout<<f[K]<<std::endl;
}