zoukankan      html  css  js  c++  java
  • 【BZOJ 1815】【SHOI 2006】color 有色图

    http://www.lydsy.com/JudgeOnline/problem.php?id=1815
    这道题好难啊,组合数学什么根本不会啊qwq
    题解详见08年的Pólya计数论文。
    主要思想是只枚举具有代表性的点的置换,算出这些点的置换造成的边的置换的保持不变的着色数(边的置换的保持不变的着色数我想了一天啊_(:з」∠)_),最后再乘上与这种具有代表性的点的置换同类的点的置换总数就可以了。
    WA了好几次,中间一个地方忘取模了qwq

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 60;
    
    int n, m, p;
    
    int GCD(int a, int b) {return b ? GCD(b, a % b) : a;}
    
    int ipow(int a, int b) {
    	int ret = 1, w = a;
    	while (b) {
    		if (b & 1) ret = 1ll * ret * w % p;
    		w = 1ll * w * w % p;
    		b >>= 1;
    	}
    	return ret;
    }
    
    int gcd[N][N], powm[N * N], jc[N], njc[N], ni[N];
    
    int L[N], ans = 0;
    
    void solve(int tot) {
    	int res = jc[n], cnt = 1, ret = 0;
    	for (int i = 1; i <= tot; ++i)
    		res = 1ll * res * ni[L[i]] % p;
    	for (int i = tot - 1; i >= 0; --i) {
    		if (L[i] != L[i + 1]) {
    			res = 1ll * res * njc[cnt] % p;
    			cnt = 1;
    			continue;
    		}
    		++cnt;
    	}
    	
    	for (int i = 1; i <= tot; ++i)
    		ret += (L[i] >> 1);
    	for (int i = 1; i <= tot; ++i)
    		for (int j = 1; j < i; ++j)
    			ret += gcd[L[i]][L[j]];
    	(ans += 1ll * res * powm[ret] % p) %= p;
    }
    
    void dfs(int tmp, int last, int rest) {
    	if (rest == 0) {
    		solve(tmp - 1);
    		return;
    	}
    	for (int i = last; i <= rest; ++i) {
    		L[tmp] = i;
    		dfs(tmp + 1, i, rest - i);
    	}
    }
    
    int main() {
    	scanf("%d%d%d", &n, &m, &p);
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= i; ++j)
    			gcd[i][j] = GCD(i, j);
    	
    	powm[0] = 1;
    	for (int i = 1, top = n * n; i <= top; ++i)
    		powm[i] = 1ll * powm[i - 1] * m % p;
    	
    	jc[0] = njc[0] = ni[0] = 1;
    	for (int i = 1; i <= n; ++i) {
    		jc[i] = 1ll * jc[i - 1] * i % p;
    		ni[i] = ipow(i, p - 2);
    		njc[i] = 1ll * njc[i - 1] * ni[i] % p;
    	}
    	
    	dfs(1, 1, n);
    	printf("%d
    ", 1ll * ans * njc[n] % p);
    	return 0;
    }
    
  • 相关阅读:
    eslint 的 env 配置是干嘛使的?
    cookie httpOnly 打勾
    如何定制 antd 的样式(theme)
    剑指 Offer 66. 构建乘积数组
    剑指 Offer 65. 不用加减乘除做加法
    剑指 Offer 62. 圆圈中最后剩下的数字
    剑指 Offer 61. 扑克牌中的顺子
    剑指 Offer 59
    剑指 Offer 58
    剑指 Offer 58
  • 原文地址:https://www.cnblogs.com/abclzr/p/6438920.html
Copyright © 2011-2022 走看看