Loading

Gym-101194H Great Cells 思维,组合计数

Gym-101194H Great Cells 思维,组合计数

题意

给定\(N \times M\)的矩阵。

定义好点为,该点的大小严格大于该行和该列的每个其他格子的大小。

现可在每个点赋值\([1,K]\)。记\(A_g\)为好点个数的\(g\)的赋值方案数。

\[\sum_{g=0}^{NM}(g+1)\cdot A_g mod(1e9+7) \]

\[1 \leq T \leq 20\\ 1\leq N,M,k \leq200 \]

分析

一眼DP,发现太复杂。观察式子,可以拆为

\[A_g + g\cdot A_g \]

对前面的求和明显就是总方案数\(K^{NM}\)

后面的我们利用系数\(g\)启发,可以理解为答案把每个好点都贡献一遍\(A_g\),那么总的来看,每个好点的贡献就是这个好点的总方案数,这个的计算方法只需要枚举这个点做为好点时的大小,它会限制\(N+M-2\)个点,其余的点随意。

故答案为

\[NM\sum_{i=2}^K(i-1)^{NM-2}\times K^{(N-1)(M-1)} + K^{NM} \]

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
typedef long long ll;

const ll MOD = 1e9 + 7;

ll rd(){
	ll x = 0;
	int f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9'){
		if(ch == '-')  f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9'){
		x =x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
} 

ll ksm(ll a,ll b,ll m){
	ll ans = 1;
	ll base = a;
	while(b){
		if(b & 1) {
			ans *= base;
			ans %= m;
		}
		base *= base;
		base %= m;
		b >>= 1;
	}
	return ans;
}

int main(){
	int kase = 0;
	int T = rd();
	while(T--){
		int n = rd();
		int m = rd();
		int k = rd();
		ll ans = 0;
		for(int i = 2;i <= k;i++){
			ans += ksm(i - 1,n + m - 2,MOD) * ksm(k,n * m - n - m + 1,MOD) % MOD;
			ans %= MOD; 
		}		
		ans *= n * m;
		ans %= MOD;
		ans += ksm(k,n * m,MOD);
		ans %= MOD;
		printf("Case #%d: %lld\n",++kase,ans);
	}
}
posted @ 2021-03-03 21:21  MQFLLY  阅读(56)  评论(0编辑  收藏  举报