[UVALive - 7040]Color [容斥 恰好k个]

版权声明:将来的你一定会感谢现在努力的你!!!! https://blog.csdn.net/qq_37383726/article/details/83188883

在这里插入图片描述

题意: 用m种颜色染一个线性格子,相邻格子颜色不同,问恰好染k种颜色的方案数.
至多用k个颜色的方案数目为 k ( k 1 ) k * (k - 1)
但是要求的是恰好k个颜色,考虑容斥
A i A_i 表示不用 i i号颜色 然后考虑对立面,
A 1 A 2 . . . A k | \overline{A_1} \cap \overline{A_2} \cap...\cap\overline{A_k} | = k ( k 1 ) n 1 A 1 A 2 . . . A k =k * (k - 1)^{n-1} -|{A_1}\cup{A_2}\cup{...}\cup{A_k}|
= k ( k 1 ) n 1 A i + A i A j + . . . + ( 1 ) k A 1 A 2 . . . A k = k*(k-1)^{n-1}-\sum|A_i|+\sum|A_i\cap A_j|+...+(-1)^k\sum|A_1 \cap A_2\cap...\cap A_k|
A i = C k 1 ( k 1 ) ( k 2 ) n 1 \sum|A_i| = C_k^1*(k-1)*(k-2)^{n-1}
A i 1 A i 2 . . . A i j = C k j ( k j ) ( k j 1 ) n 1 \sum|A_{i_1} \cap A_{i_2}\cap...\cap A_{i_j}| = C_k^{j}*(k-j)*(k-j-1)^{n-1}
a n s = A 1 A 2 . . . A k C m k ans=| \overline{A_1} \cap \overline{A_2} \cap...\cap\overline{A_k} |*C_m^k
C m k C_{m}^{k} 可以利用递推得到: C m k = C m k 1 m k + 1 k C_{m}^{k} = C_{m}^{k-1} * \frac {m-k+1}{k}
代码

/***********************************************
Author        :lzs
Created Time  :2018年10月19日 星期五 17时49分21秒
File Name     :Color.cpp
 ************************************************/
#include <bits/stdc++.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define rep(i, l, r) for(int i = l; i < r; i++)
#define per(i, r, l) for(int i = r; i >= l; i--)
#define dbgln(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n"
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"


typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;

const int N = (int) 1e6 + 20;
const int M = (int) 1e6 + 11;
const int MOD = (int) 1e9 + 7;
const int INF = (int) 0x3f3f3f3f;
const ll INFF = (ll) 0x3f3f3f3f3f3f3f3f;
/*-----------------------------------------------------------*/

int Pow(int a, int b, int c = MOD){
	int s = 1; a %= c;
	while(b){
		if(b & 1) s = s * 1ll * a % c;
		b >>= 1;
		a = a * 1ll * a % c;
	}
	return s;
}
int fac[N], inv[N], in[N];
void ini(int n){
	fac[0] = 1;
	for(int i = 1; i < n; i++) fac[i] = i * 1ll * fac[i - 1] % MOD, in[i] = Pow(i, MOD - 2);
	inv[n - 1] = Pow(fac[n - 1], MOD - 2); inv[0] = 1;
	for(int i = n - 2; i > 0; i--) inv[i] = inv[i + 1] * 1ll * (i + 1) % MOD;
}
int C(int n, int m){
	if(n < m) return 0;
	return fac[n] * 1ll * inv[n - m] % MOD * inv[m] % MOD;
}
int main(){
	ini(1000000 + 10);
	int T; scanf("%d" ,&T);
	for(int cas = 1; cas <= T; cas++){
		int n, m, k; scanf("%d%d%d", &n, &m, &k);
		int cmk = 1;
		for(int i = 1; i <= k; i++) 
			cmk = cmk * 1ll * (m - i + 1) % MOD * in[i] % MOD;
		ll ans = k * 1ll * Pow(k - 1, n - 1) % MOD;
		int cur = -1;
		for(int i = 1; i < k; i++){
			ans += cur * 1ll * C(k, i) * (k - i) % MOD * Pow(k - i - 1, n - 1) % MOD;  
			ans = (ans + MOD) % MOD;
			cur = -cur;	
		}
		ans = ans * 1ll * cmk % MOD;
		printf("Case #%d: %lld\n", cas, ans);
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37383726/article/details/83188883