版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luyehao1/article/details/83957161
题目链接:
题意:
有NM的格子矩阵,每个格子里能填区间[1,K]内中的一个数字。设一个格子是Great cell,当且仅当这个格子中的数字严格大于其所在行和所在列的其他所有数字。问有多少种不同的填法使得恰好有g个Great cell。求等式\sum_{g=0}^{nm}(g+1)*Ag mod(1e9+7)的值。
思路:
对等式进行拆分:
\sum_{g=0}^ {nm}(g+1)Ag = \sum_{g=0}^ {nm}gAg + \sum_{g=0}^ {n*m}Ag
后半部分等于A0+A1+…+Anm,就等于所有可能的情况数 = k^(nm)。
前半部分相当于每个格点的贡献和。贡献定义为每个格点当一次Great cell贡献就+1。
那么对于每个格点来说,当它选的数字是i,那么它所在行列的其他数字的选择种类数 = (i-1)^(n+m-2)种,剩余格点可以随便放,种类数 = k^(n-1)(m-1) 种,所以每个格点的贡献 = (i-1)^(n+m-2)* k^(n-1)(m-1),i属于[2,K]。
总共有nm个格点,所以最后的答案 =nm * \sum_{i=1}^ {K} (i-1)^(n+m-2)* k^(n-1)(m-1) + k^(n*m) 。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 1e5+10;
const ll mod = 1e9+7;
ll n,m,k;
ll multiply(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)
{
ans = ((ans%mod)*(a%mod)) % mod;
b--;
}
b /= 2;
a = ((a%mod)*(a%mod)) % mod;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
int Case=1;
while(T--)
{
scanf("%lld%lld%lld",&n,&m,&k);
ll ans=0;
for(int i=2;i<=k;i++){
ans+=multiply(i-1,n+m-2);
ans%=mod;
}
ans*=(n*m);
ans%=mod;
ans*=multiply(k,(n-1)*(m-1));
ans%=mod;
ans+=multiply(k,n*m);
ans%=mod;
printf("Case #%d: %lld\n",Case++,ans);
}
return 0;
}
`