1. 程式人生 > >(賽前練手 #8)BZOJ1004 [HNOI2008]Cards

(賽前練手 #8)BZOJ1004 [HNOI2008]Cards

004: [HNOI2008]Cards

Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4396 Solved: 2684 [Submit][Status][Discuss] Description

小春現在很清閒,面對書桌上的N張牌,他決定給每張染色,目前小春只有3種顏色:紅色,藍色,綠色.他詢問Sun有 多少種染色方案,Sun很快就給出了答案.進一步,小春要求染出Sr張紅色,Sb張藍色,Sg張絕色.他又詢問有多少種方 案,Sun想了一下,又給出了正確答案. 最後小春發明了M種不同的洗牌法,這裡他又問Sun有多少種不同的染色方案. 兩種染色方法相同當且僅當其中一種可以通過任意的洗牌法(即可以使用多種洗牌法,而每種方法可以使用多次)洗 成另一種.Sun發現這個問題有點難度,決定交給你,答案可能很大,只要求出答案除以P的餘數(P為質數).

Input

第一行輸入 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種洗牌法中的一種代 替,且對每種洗牌法,都存在一種洗牌法使得能回到原狀態。

Output

不同染法除以P的餘數

Sample Input

1 1 1 2 7

2 3 1

3 1 2 Sample Output

2 HINT

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

和GRB。

100%資料滿足 Max{Sr,Sb,Sg}<=20。

Source 不會群論咋做啊? 其實本題有個很重要的性質

輸入資料保證任意多次洗牌都可用這 m種洗牌法中的一種代 替,且對每種洗牌法,都存在一種洗牌法使得能回到原狀態。

所以這些洗牌法也不過是重複計算???我們將ans除以(m + 1) 根據費馬小定理這裡有個簡單的逆元,也就是說我們乘以(m + 1) ^ (p - 2)即可 那麼ans咋求呢? 很簡單的組合問題… 設n = a +b + c ans = C(n , a) + C(n - a , b) + C(n - a - b , c) 因為確定了前兩項那麼第三項就自然確定了 所以ans = C(n , a) +C(n - a , b) AC Code:

#include<bits/stdc++.h>
#define rg register
#define il inline
#define maxn 1000010
#define ll long long
using namespace std;
il ll read(){rg ll x = 0 , w = 1 ; rg char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') w = -1; ch = getchar();}while (ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0' ; ch = getchar();}return x * w;}
ll p;
ll ksm(ll x , ll k){
	ll res = x , ans = 1;
res %= p;
	while (k){
		if (k & 1) ans = ans % p * res % p;
		res = (res * res) % p;
		k >>= 1;
	}
	return ans;
}
int main(){
	ll a = read() , b = read() , c = read() , m = read();
	p = read(); 
	ll n = a + b + c;
	ll ans = 1;
	ll tmp = 1;
	for (rg ll i = 1 ; i <= a ; ++i)
		tmp = tmp * (n - i + 1) / i;//不要寫成 *= 了....
	ans = ans * (tmp % p) % p;
	n -= a , tmp = 1;
	for (rg ll i = 1 ; i <= b ; ++i)
		tmp = tmp * (n - i + 1) / i;
	ans = ans * (tmp % p) % p;
	printf("%lld" , (ans * (ksm(m + 1 , p - 2) % p)) % p);
}