Gym-101194H Great Cells 思维,组合计数
题意
给定(N imes M)的矩阵。
定义好点为,该点的大小严格大于该行和该列的每个其他格子的大小。
现可在每个点赋值([1,K])。记(A_g)为好点个数的(g)的赋值方案数。
问
[sum_{g=0}^{NM}(g+1)cdot A_g mod(1e9+7)
]
[1 leq T leq 20\
1leq N,M,k leq200
]
分析
一眼DP,发现太复杂。观察式子,可以拆为
[A_g + gcdot A_g
]
对前面的求和明显就是总方案数(K^{NM})
后面的我们利用系数(g)启发,可以理解为答案把每个好点都贡献一遍(A_g),那么总的来看,每个好点的贡献就是这个好点的总方案数,这个的计算方法只需要枚举这个点做为好点时的大小,它会限制(N+M-2)个点,其余的点随意。
故答案为
[NMsum_{i=2}^K(i-1)^{NM-2} imes 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
",++kase,ans);
}
}