bzoj 4487: [Jsoi2015]染色問題
阿新 • • 發佈:2018-12-17
簡述題意:
演算法:組合數+容斥(不好推)
難度:NOIP+
題解:
首先,你可以用O(nmc)的時間複雜度水過這道題!
公式為:①
我是不會告訴你這公式很好推的,反正我自己推不出來,看完題解,大概可能明白了吧
如果你不甘心於水過這道題,你可以對上面的公式進行優化,優化成時間複雜度為O(n*m*logc)
推導過程如下:
②
①<=>②(只是調換了的順序...)
又因為
所以,綜合②③式可得, ④
因此,利用 ④式,就可以在O(nmlogc)的時間複雜度內,解決這道題!
程式碼如下:
#include <bits/stdc++.h> #define ll long long #define N 405 using namespace std; const ll p=1000000007; ll inv[N],jc[N]; void ny() { inv[0]=1; inv[1]=1; for(int i = 2;i <= 400;i++) { inv[i]=(p-p/i)*inv[p%i]%p; } jc[1]=1; for(int i = 2;i <= 400;i++) { jc[i]=((jc[i-1]%p)*i)%p; } for(int i = 2;i <= 400;i++) { inv[i]=(inv[i-1]*inv[i])%p; } } ll powermod(ll x,ll y) { ll ret=1; while(y) { if(y%2) { ret=ret*x%p; } y=y/2; x=x*x%p; } return ret; } ll C(int n, int m) { return jc[n]*inv[m]%p*inv[n-m]%p; } ll ans; int main() { int n,m,kk; scanf("%d%d%d",&n,&m,&kk); ny(); for (int i = 0;i <= n;i++) { for (int k = 0;k <= kk;k++) { ll qwq=C(n,i)*C(kk,k)%p; ll orz=powermod((1-powermod(k+1,i)+p)%p,m); qwq=qwq*orz%p; if ((n+m+kk-i-k)%2) qwq=-qwq; ans=(ans+qwq)%p; } } printf("%lld\n",(ans+p)%p); return 0 ; }