2016年ACM/ICPC Asia China-Final (Shanghai) Contest H題(思維)
阿新 • • 發佈:2018-11-11
題意:在一個n*m的矩陣內填整數,數字在[1...K]範圍內。矩陣中某格的數為great number當且僅當與它同行同列的數字都嚴格比它小。即Ag為矩陣中恰有g個great number的填數方案數,求
(n,m,k<=200n,m,k<=200)
我感覺網上的題解說的比較粗略,根本就很難看懂,雖然看似簡單,但是講的不夠詳細。
例:
實際上,除去k^(n*m)的任意填法(即g+1那個1)之後只要有一個great number出現,我們就統計一次答案。因為剛好是g*Ag。
對於每個格子,是great number ,假設這個格子填i,則其所在行、列的共n+m-2個格子只有(i-1)種選擇,其他的(n-1)*(m-1)個格子就可以隨便填了(對於這些格子,每個格子有k種選擇)(因為每個出現g個great number的矩陣會被統計g次)。
所以列舉i從2到k如上式那樣統計,最後再加上k^(n*m)取模,就是答案。這樣就很容易理解了。
程式碼:
#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f using namespace std; const ll mo=1e9+7; ll n,m,k; ll power(ll a,ll n) //a的n次方mod { ll ans=1; a=a%mo; while (n) { if(n&1) ans=(ans*a)%mo; n>>=1; a=(a*a)%mo; } return ans; } int main() { int T,cas=1; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld",&n,&m,&k); ll ans=0; for(ll i=2;i<=k;i++) { ans=(ans+n*m%mo*power(i-1,n+m-2)%mo*power(k,(n-1)*(m-1))%mo)%mo; } ans=(ans+power(k,n*m))%mo; printf("Case #%d: %lld\n",cas++,ans); // if(flag) puts("Yes"); else puts("No"); } return 0; }