source:題目鏈接
題意:這是2016 ACM-ICPC China-Final的H題,在N×M的網格里填[1,K]的整數,定義一個格子是great的,如果滿足這個格子中的數是本行和本列中嚴格的最大值。定義A-g爲網格中恰好有g個great格子的填法數,求Σ(g+1)A-g
思路:這題乍一看需要用組合數學 容斥原理計算A-g,但是這樣做比較麻煩複雜。但其實這題是(g+1)的套路。。。簡便做法是觀察整體,把問題轉化成每個位置是great格子對最終答案的貢獻和,這樣就繞開了A-g的計算。
首先,考慮整體的填法:K^(M×N)——這個是容易計算的,那麼我們先企圖用整體填法數化簡待求式!我們發現將待求式展開,後面的ΣA-g的和便是整體的填法數。(一般都需要先拿整體化簡一把!)
於是現在只需着手計算Σg*A-g,這個就用貢獻和的思想轉化,因爲有g個great格的填法數乘了個g相當於攤到了這g個位置上,也就是說每個great格獨立了,也即每一個格是great格對Σg*A-g貢獻=使這個格是great的所有填法總數:
Contrib=Σ(i=1到i=K-1)i^(N-1+M-1)×K^[(N-1)×(M-1)] (轉化爲貢獻和,有點智力題的感覺orz..)
這裏注意一點:以上公式沒有考慮n=m=1的情況,因爲這時填1也算是great格(而以上公式從填2開始考慮的)
從而最後
ans=Contrib×N×M+K^(M×N)
代碼如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL mod=1e9+7;
LL qmod(LL a,LL b) //快速冪
{
LL ans=1;
while(b)
{
if(b&1==1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
int t,T;
LL m,n,k,ans;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%lld%lld%lld",&n,&m,&k);
ans=0;
for(LL i=1;i<k;i++)
{
ans=(ans+qmod(i,m+n-2))%mod;
}
ans=ans*qmod(k,(m-1)*(n-1))%mod;
ans=(ans*n%mod)*m%mod;
ans=(ans+qmod(k,n*m))%mod;
if(m==1 && n==1) ans=(ans+1)%mod; //m=n=1時特判!!!
printf("Case #%d: %lld\n",t,ans);
}
return 0;
}