1. 程式人生 > >2016 ACM ECFinal Problem H. Great Cells

2016 ACM ECFinal Problem H. Great Cells

題目連結:

2016 ACM ECFinal

題意:

有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^(n

m)。

前半部分相當於每個格點的貢獻和。貢獻定義為每個格點當一次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;
}

`