日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 1815: [Shoi2006]color 有色图 [Polya DFS 重复合并]

發布時間:2025/3/20 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 重复合并]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。