BZOJ 1815: [Shoi2006]color 有色图 [Polya DFS 重复合并]
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 1815: [Shoi2006]color 有色图 [Polya DFS 重复合并]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
題意:
染色圖是無向完全圖,且每條邊可被染成k種顏色中的一種。
兩個染色圖是同構的,當且僅當可以改變一個圖的頂點的編號,使得兩個染色圖完全相同。
問N個頂點,k種顏色,本質不同的染色圖個數(模質數N≤53,P<109)。
想了一節課和一中午又看了課件
相同類型的循環合并的想法很巧妙
首先,點的置換對應唯一邊的置換,我們可以枚舉所有點的置換,找出每個置換下邊置換的循環有多少個,然后套$Polya$公式
但是復雜度帶嘆號
我們發現,很多點置換類型是一樣的,我們可以對$n$搜索劃分來枚舉點置換的類型(即每個循環的長度),然后找出這種類型的置換有多少個
設每個循環長度$L_1,L_2,...,L_n$,那么相同類型的置換就相當于每個循環做圓排列,然后消除循環長度相同的影響
$\frac{n!}{L_1 L_2...L_n s_1! s_2!...s_t!}$
$s$為相同的長度的個數
那么如何從點的置換得到邊的置換?
同一個循環里的邊,他們的循環個數為$\frac{L}{2}$,具體可以把點排成一個圈畫圖觀察一下
兩個循環之間的邊,他們的循環長度為$LCM(L_1,L_2)$,共有$L_1*L_2$條邊,則個數為$GCD(L_1,L_2)$
?
然后就可以做了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=60; typedef long long ll; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}return x*f; } int n,m,P; ll inv[N],fac[N],facInv[N]; void ini(){inv[1]=1;fac[0]=facInv[0]=1;for(int i=1;i<=n;i++){if(i!=1) inv[i]=-P/i*inv[P%i]%P;if(inv[i]<0) inv[i]+=P;fac[i]=fac[i-1]*i%P;facInv[i]=facInv[i-1]*inv[i]%P;} } int L[N],tot; ll sum,ans; inline int gcd(int a,int b){return b==0 ? a : gcd(b,a%b);} inline ll Pow(ll a,int b){ll re=1;for(;b;b>>=1,a=a*a%P)if(b&1) re=re*a%P;return re; } inline void mod(ll &x){if(x>=P) x-=P;} void dfs(int d,int now){if(d==n){int lo=0;ll cnt=fac[n],same=1;sort(L+1,L+1+tot);//printf("tot %d\n",tot);//for(int i=1;i<=tot;i++) printf("%d ",L[i]);puts("\n end");for(int i=1;i<=tot;i++){lo+=L[i]/2;for(int j=i+1;j<=tot;j++) lo+=gcd(L[i],L[j]);cnt=cnt*inv[L[i]]%P;if(i!=1&&L[i]==L[i-1]) same++;else if(same!=1) cnt=cnt*facInv[same]%P,same=1;}if(same!=1) cnt=cnt*facInv[same]%P;//printf("hi %d %lld\n",lo,cnt);mod(sum+=cnt);mod(ans+=cnt%P*Pow(m,lo)%P);//puts("\n");}else{for(int j=now;d+j<=n;j++){L[++tot]=j;dfs(d+j,j);tot--;}} } int main(){freopen("in","r",stdin);n=read();m=read();P=read();ini();dfs(0,1);//printf("%lld %lld\n",ans,sum);ans=ans*Pow(sum,P-2)%P;printf("%lld",ans); }?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的BZOJ 1815: [Shoi2006]color 有色图 [Polya DFS 重复合并]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 检查类型是否包含iterator
- 下一篇: 如何学习Python课程