首页 > 其他分享 >[ABC236H] Distinct Multiples

[ABC236H] Distinct Multiples

时间:2022-08-31 12:24:30浏览次数:101  
标签:连通 系数 ABC236H Distinct void 容斥 template inline Multiples

题目传送门

Solution

首先不难想到容斥,我们可以钦定若干关系 \((u,v)\),表示 \(u,v\) 的值相同,那么我们不妨设 \(g(i)\) 表示至少有 \(i\) 种这种关系的方案数,可以发现答案就是 \(\sum_{i=0} (-1)^i g(i)\)。后面的话我们把这种关系看成一条边。

考虑到实际上一个连通块的值其实都是相同的,所以我们可以对于一个连通块一起考虑,并且算出它的容斥系数。假设该连通块大小为 \(n\),应该求得的容斥系数为 \(f(n)\),可以看出 \(f(1)=1\)。首先如果不钦定这个连通块通过这些关系保持联通,那么容斥系数是 \(0\),因为对于一条边选或不选的容斥系数可以抵消。所以我们再减去不连通的容斥系数就是联通的容斥系数了。我们可以考虑枚举 \(1\) 所属的连通块,如果这个连通块的大小 \(\le n-2\),那么后面的那些点容斥系数就是 \(0\),不会产生贡献,所以我们只需要枚举是哪个孤立点,因此可以得出递推式:

\[f(n)=-(n-1)f(n-1) \]

后面的话直接状压 dp,转移的话直接枚举一个钦定位置所属子集直接转移即可。

Code

#include <bits/stdc++.h>
using namespace std;
 
#define Int register int
#define mod 998244353
#define int __int128
#define MAXN 25
 
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
 
int n,m,s[MAXN],h[MAXN],f[1 << 16],g[1 << 16];
int lowbit (int x){return x & (-x);}
int lcm (int a,int b){return a / __gcd (a,b) * b;}
 
signed main(){
	read (n,m);
	for (Int x = 1;x <= n;++ x) read (s[x]);
	h[1] = 1;for (Int i = 2;i <= n;++ i) h[i] = mod - (i - 1) * h[i - 1] % mod;
	for (Int S = 1;S < (1 << n);++ S){
		int v = 1,tot = 0;
		for (Int x = 1;x <= n;++ x) if (S >> x - 1 & 1){
			v = lcm (v,s[x]),tot ++;
			if (v > m) break;
		}
		g[S] = h[tot] * (m / v) % mod;
	}
	for (Int S = 1;S < (1 << n);++ S){
		f[S] = g[S];int nS = S ^ lowbit(S);
		for (Int T = nS;;T = (T - 1) & nS){
			int nT = T ^ lowbit (S);
			(f[S] += g[nT] * f[S ^ nT] % mod) %= mod;
			if (!T) break;
		}
	}
	write (f[(1 << n) - 1]),putchar ('\n');
	return 0;
}

标签:连通,系数,ABC236H,Distinct,void,容斥,template,inline,Multiples
From: https://www.cnblogs.com/Dark-Romance/p/16642622.html

相关文章