abc236h

图计数相关

思路

钦定若干组组内相等,每组的方案为 。状压,枚举包含 的子集 乘方案数和大小为 的组的容斥系数转移。

对于 个不等关系钦定 个相等的容斥系数为 。钦定组内相等的容斥系数为构成大小为 无向连通图的选边方案的容斥系数之和。

仿照 无向连通图计数 个点乱连的系数为 。减去不连通图的贡献, 个点的组的容斥系数之和为

code

int n,m,a[maxn];
int f[17];
int dp[1<<maxn],val[1<<maxn];
void work(){
	n=read();m=read();
	for(int i=0;i<n;i++)a[i]=read();
	for(int i=1;i<=n;i++){
		f[i]=(i==1);
		for(int j=1;j<i;j++)f[i]-=C(i-1,j-1)*f[j]*(i-j==1)%mod;
		f[i]+=mod,f[i]%=mod;
	}
	for(int s=1;s<(1<<n);s++){
		int p=__lg(s&(-s)),gg=gcd(val[s^(1<<p)],a[p]);
		if(!val[s^(1<<p)])val[s]=a[p];
		else if(a[p]/gg>m/val[s^(1<<p)])val[s]=m+1;
		else val[s]=a[p]/gg*val[s^(1<<p)];
	}
	dp[0]=1;
	for(int s=1;s<(1<<n);s++){
		int p=__lg(s&(-s));
		for(int t=s;t;t=(t-1)&s)if(t&(1<<p)){
			(dp[s]+=(m/val[t])%mod*dp[s^t]%mod*f[__builtin_popcount(t)])%=mod;
		}
	}
	printf("%lld\n",dp[(1<<n)-1]);
}