CF [2016-2017 ACM-ICPC CHINA-Final][GYM 101194 H] Great Cells

好久之前作的一道思博題了,今天來補一補。git

大體題意:在一個\(n*m\)的矩陣內填整數,數字在\([1,k]\)範圍內。矩陣中某格的數爲great number當且僅當與它同行同列的數字都嚴格比它小。記\(A_g\)爲矩陣中恰有\(g\)個great number的填數方案數,求\(\sum_{g=0}^{nm}(g+1)\cdot A_g\)。(\(n,m,k\le200\))ui

首先咱們能夠看出,上界一定是\(min(n,m)\),這個不解釋了吧spa

而又有一個性質,\(\sum_{g=0}^{min(n,m)} A_g=K^{nm}\)。即全部的great number方案數等於總填數方案數code

因此咱們拆出\(\sum_{g=0}^{min(n,m)} A_g\)因而只須要考慮如何構造出\(\sum_{g=0}^{min(n,m)} g\cdot A_g\)it

咱們仍是回頭再看一眼題面\(g\)到底是什麼:io

\(A_g\)爲矩陣中恰有\(g\)個great number的填數方案數class

那麼每個great number在該方案下都對答案貢獻\(1\)static

還不懂?再轉化一步,也就是每一個格子上的數爲great number的方案數之和di

這就是\(\sum_{g=0}^{min(n,m)} g\cdot A_g=nm\cdot\sum_{i=2}^k (i-1)^{n+m-2}\cdot k^{(n-1)\cdot (m-1)}\)while

而後各類亂搞就能夠了

CODE

#include<cstdio>
#include<cctype>
using namespace std;
const int mod=1e9+7;
int t,n,m,k,ans;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline int quick_pow(int x,int p)
{
    long long tot=1;
    while (p)
    {
        if (p&1) tot=tot*1LL*x%mod;
        x=1LL*x*x%mod; p>>=1;
    }
    return (int)tot;
}
inline void inc(int &x,int y)
{
    if ((x+=y)>=mod) x-=mod;
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i,j; read(t); 
    for (i=1;i<=t;++i)
    {
        read(n); read(m); read(k);
        for (ans=0,j=2;j<=k;++j)
        inc(ans,1LL*quick_pow(j-1,n+m-2)*quick_pow(k,n*m-n-m+1)%mod);
        ans=(1LL*ans*n*m)%mod; inc(ans,quick_pow(k,n*m));
        printf("Case #%d: %d\n",i,ans); 
    }
    return 0;
}
相關文章
相關標籤/搜索