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);
}
}