题意

摆。

题解

用背包维护不定点,套 Burside 引理。

代码

const int N = 30, M = 70;

inline ll Read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

namespace Main {
	int sr, sb, sg, n, m, mod;
	int f[N][N][N];
	int a[M], siz[N], vis[N], cnt;
	int add(int a, int b) { return a + b > mod? a + b - mod: a + b; }
	int dec(int a, int b) { return a - b < 0? a - b + mod: a - b; }
	int mul(int a, int b) { return 1ll * a * b % mod; }
	int qpow (int a, ll b) {
		int ans = 1;
		for (; b; b >>= 1, a = mul(a, a))
			if (b & 1) ans = mul(ans, a);
		return ans;
	}
	int ans;
	void dp (int n) {
		memset (f, 0, sizeof f);
		f[0][0][0] = 1;
		for (int i = 1; i <= n; i++)
			for (int r = sr; ~r; --r)
			for (int b = sb; ~b; --b)
			for (int g = sg; ~g; --g) {
				if (r >= siz[i]) f[r][b][g] = add(f[r][b][g], f[r - siz[i]][b][g]);
				if (b >= siz[i]) f[r][b][g] = add(f[r][b][g], f[r][b - siz[i]][g]);
				if (g >= siz[i]) f[r][b][g] = add(f[r][b][g], f[r][b][g - siz[i]]);
			}
		ans = add(ans, f[sr][sb][sg]);
	}
	int main () {
		sr = Read(), sb = Read(), sg = Read(), m = Read(), mod = Read();
		n = sr + sb + sg;
		for (int i = 1; i <= n; i++) siz[i] = 1;
		dp(n);
		for (int k = 1; k <= m; k++) {
			for (int i = 1; i <= n; i++) a[i] = Read();
			cnt = 0;
			memset (vis, 0, sizeof vis);
			for (int i = 1; i <= n; i++) {
				if (vis[i]) continue;
				vis[i] = 1;
				int tmp = 1;
				for (int j = a[i]; j != i; j = a[j]) {
					vis[j] = 1;
					tmp++;
				}
				siz[++cnt] = tmp;
			}
			dp(cnt);
		}
		printf ("%d\n", mul(ans, qpow(m + 1, mod - 2)));
		return 0;
	}
}

int main () {
	string str = "";
//	freopen((str + ".in").c_str(), "r", stdin);
//	freopen((str + ".out").c_str(), "w", stdout);
	Main::main();
	return 0;
}
EOF

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。

博客信息

作者
Jayun
时间
2024-02-28 15:59:44
博客类型