zoukankan      html  css  js  c++  java
  • P1446 [HNOI2008]Cards

    $ color{#0066ff}{ 题目描述 }$

    小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.

    进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绿色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.

    Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).

    (color{#0066ff}{输入格式})

    第一行输入 5 个整数:Sr,Sb,Sg,m,p(m<=60,m+1<p<100)。n=Sr+Sb+Sg。接下来 m 行,每行描述一种洗牌法,每行有 n 个用空格隔开的整数 X1X2...Xn,恰为 1 到 n 的一个排列,表示使用这种洗牌法,第 i位变为原来的 Xi位的牌。输入数据保证任意多次洗牌都可用这 m种洗牌法中的一种代替,且对每种

    洗牌法,都存在一种洗牌法使得能回到原状态。

    100%数据满足 Max{Sr,Sb,Sg}<=20。

    (color{#0066ff}{输出格式})

    不同染法除以P的余数

    (color{#0066ff}{输入样例})

    1 1 1 2 7
    2 3 1
    3 1 2
    

    (color{#0066ff}{输出样例})

    2
    

    (color{#0066ff}{数据范围与提示})

    有2 种本质上不同的染色法RGB 和RBG,使用洗牌法231 一次可得GBR 和BGR,使用洗牌法312 一次 可得BRG 和GRB。

    [HNOI2008]

    (color{#0066ff}{题解})

    因为有颜色数量的限制,所以Polya就不太可行了

    没事,我们还有Burnside

    于是我们要找每个置换下不变的方案数

    不难发现,对于每个循环,循环中的颜色必须相同才行

    于是把当前置换的循环处理出来,当成物品跑01背包,就可以求出不变的方案数

    注意还有额外的一种置换是不洗牌,也就是说不变,要特殊处理

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    int f[50][50][50];
    bool vis[100];
    int mp[100];
    int siz[100];
    int ans;
    int a, b, c, m, mod, n;
    LL ksm(LL x, LL y) {
    	LL re = 1LL;
    	while(y) {
    		if(y & 1) re = re * x % mod;
    		x = x * x % mod;
    		y >>= 1;
    	}
    	return re;
    }
    int work(int flag) {
    	memset(f, 0, sizeof f);
    	for(int i = 1; i <= n; i++) vis[i] = 0, siz[i] = 0;
    	int num = 0;
    	if(!flag) {
    		for(int i = 1; i <= n; i++) {
    			if(vis[i]) continue;
    			num++;
    			int now = i;
    			while(!vis[now]) vis[now] = true, siz[num]++, now = mp[now];
    		}
    	}
    	else {
    		num = n;
    		for(int i = 1; i <= n; i++) siz[i] = 1;
    	}
    	f[0][0][0] = 1;
    	for(int i = 1; i <= num; i++)
    		for(int A = a; A >= 0; A--)
    			for(int B = b; B >= 0; B--)
    				for(int C = c; C >= 0; C--) {
    					if(A >= siz[i]) (f[A][B][C] += f[A - siz[i]][B][C]) %= mod;
    					if(B >= siz[i]) (f[A][B][C] += f[A][B - siz[i]][C]) %= mod;
    					if(C >= siz[i]) (f[A][B][C] += f[A][B][C - siz[i]]) %= mod;
    				}
    	return f[a][b][c];
    }
    
    int main() {
    	n = (a = in()) + (b = in()) + (c = in());
    	m = in(), mod = in();
    	for(int i = 1; i <= m; i++) {
    		for(int j = 1; j <= n; j++) mp[j] = in();
    		(ans += work(0)) %= mod;
    	}
    	(ans += work(1)) %= mod;
    	printf("%lld", 1LL * ans * ksm(m + 1, mod - 2) % mod);
    	return 0;
    }
    
  • 相关阅读:
    嵌套使用Using Statement造成对象被dispose多次 CA2202
    ASP.NET 4.0: 请求验证模式变化导致ValidateRequest=false失效
    IIS 7.0的集成模式和经典模式
    设计模式之—简单工厂设计模式
    c#总结(一)
    数据库分离附加工具
    深入理解C#之 参数传递 ref out params
    ASP.NET MVC 学习笔记(一)
    C#实现根据IP 查找真实地址
    c# 新特性
  • 原文地址:https://www.cnblogs.com/olinr/p/10426953.html
Copyright © 2011-2022 走看看