Paint Box(塗色要求相鄰不能同色,求方案數)
阿新 • • 發佈:2020-09-02
題:https://ac.nowcoder.com/acm/problem/13884
題意:給定n,m,k,代表n個連續的格子,要求用m種顏色去塗色,要求圖上的色的種類恰好為k。(n,m<=1e9,k<=1e6)
分析:恰好的字眼,說明要轉成,不多於或至少的答案去做,再用容斥去求;
假設用不超過k種顏色去塗格子(相鄰不能同色)的方案為xk =k*(k-1)n-1,表示第一個格子有k種顏色可選,接下來的格子由於相鄰不能同色,所以每個格子只有k-1的選擇;
但當前只是不超過,若要正好為k種顏色,那麼根據容斥原理,ans=xk-C(k,k-1)*xk-1+C(k,k-2)*xk-2+.....+(-1)k
最後只要在m種顏色中取k種顏色,那麼只要ans再乘上C(m,k)即可,由於m很大,但是k在合理範圍內,所以利用k來進行求值即可。
#include<bits/stdc++.h> using namespace std; #define pb push_back #define MP make_pair typedef long long ll; const int M=1e6+15; const int inf=0x3f3f3f3f; const ll INF=1e18; const int mod=1e9+7; ll fac[M],facinv[M]; ll ksm(ll x,ll y){ ll tView Code=1; while(y){ if(y&1) t=(t*x)%mod; x=(x*x)%mod; y>>=1; } return t; } ll inv(ll x){ return ksm(x,mod-2)%mod; } ll C(ll x,ll y){ if(y>x||x<0||y<0) return 0; if(y==0||x==y) return 1; return fac[x]*facinv[y]%mod*facinv[x-y]%mod; }void init(){ fac[0]=1; for(int i=1;i<=M;i++) fac[i]=1ll*fac[i-1]*i%mod; facinv[M-1]=ksm(fac[M-1],mod-2); for(int i=M-2;i>=0;i--) facinv[i]=facinv[i+1]*(i+1)%mod; } int main(){ init(); int T; scanf("%d",&T); while(T--){ ll n,m,k; scanf("%lld%lld%lld",&n,&m,&k); ll ans=0; ///容斥 for(int dis=1,i=0;i<k;i++,dis=-dis){ ans=(ans+dis*C(k,k-i)*(k-i)%mod*ksm(k-i-1,n-1)%mod+mod)%mod; } ///乘上C(m,k); for(int i=0;i<k;i++) ans=ans*(m-i)%mod*inv(k-i)%mod; printf("%lld\n",ans); } return 0; }