BZOJ4766 文艺计算姬
Description
"奋战三星期,造台计算机"。小W响应号召,花了三星期造了台文艺计算姬。文艺计算姬比普通计算机有更多的艺
术细胞。普通计算机能计算一个带标号完全图的生成树个数,而文艺计算姬能计算一个带标号完全二分图的生成树
个数。更具体地,给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图K_{n,m},计算姬能快
速算出其生成树个数。小W不知道计算姬算的对不对,你能帮助他吗?
Input
仅一行三个整数n,m,p,表示给出的完全二分图K_{n,m}
1 <= n,m,p <= 10^18
Output
仅一行一个整数,表示完全二分图K_{n,m}的生成树个数,答案需要模p。
Sample Input
2 3 7
Sample Output
5
显然可以用矩阵树定理,但是是$O(n^3)$
显然这道题是不行的
考虑打表,附上打表程序
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 int a[301][301],Mod=1e9+7,n,m,ans; 9 char s[301][301]; 10 void guass() 11 {int i,j,k; 12 n=n+m-1; 13 ans=1; 14 for (i=1;i<=n;i++) 15 { 16 for (j=1;j<=n;j++) 17 { 18 a[i][j]=(a[i][j]+Mod)%Mod; 19 } 20 } 21 for (i=1;i<=n;i++) 22 { 23 for (j=i+1;j<=n;j++) 24 { 25 while (a[j][i]) 26 { 27 int t=a[i][i]/a[j][i]; 28 for (k=i;k<=n;k++) 29 { 30 a[i][k]=(a[i][k]-1ll*t*a[j][k]%Mod+Mod)%Mod; 31 swap(a[i][k],a[j][k]); 32 } 33 ans*=-1; 34 } 35 } 36 ans=1ll*ans*a[i][i]%Mod; 37 } 38 ans=(ans+Mod)%Mod; 39 } 40 int main() 41 {int i,j; 42 cin>>n>>m>>Mod; 43 for (i=1;i<=n;i++) 44 { 45 for (j=n+1;j<=n+m;j++) 46 { 47 a[i][j]--;a[j][i]--; 48 a[i][i]++;a[j][j]++; 49 } 50 } 51 guass(); 52 cout<<n+1-m<<' '<<m<<' '<<ans; 53 }
分解因数后发现
$ans=n^{m-1}*m^{n-1}$
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 lol ans1,ans2,n,m,Mod,ans; 9 lol qadd(lol x,lol y) 10 { 11 lol res=0; 12 while (y) 13 { 14 if (y&1) 15 { 16 res=(res+x); 17 if (res>=Mod) res-=Mod; 18 } 19 x=(x+x); 20 if (x>=Mod) x-=Mod; 21 y>>=1; 22 } 23 return res; 24 } 25 lol qpow(lol x,lol y) 26 { 27 lol res=1; 28 while (y) 29 { 30 if (y&1) res=qadd(res,x); 31 x=qadd(x,x); 32 y>>=1; 33 } 34 return res; 35 } 36 int main() 37 { 38 cin>>n>>m>>Mod; 39 ans1=qpow(n,m-1); 40 ans2=qpow(m,n-1); 41 ans=qadd(ans1,ans2); 42 cout<<ans; 43 }