1. 程式人生 > >poj2409:Let it Bead(置換群 polya定理)

poj2409:Let it Bead(置換群 polya定理)

pre int lose cnblogs 翻轉 空格 else 位置 長度

  題目大意:長度為n的項鏈,要染m種顏色,可以通過旋轉或翻轉到達的狀態視為同一種,問有多少種染色方案。

  學了一波polya定理,發現很好理解啊,其實就是burnside定理的擴展。技術分享

  burnside定理告訴我們不同染色方案數是每種置換的不變元素個數除以置換總數,而polya定理就是在這個基礎上用公式計算出置換的不變元素個數。而且polya定理非常好理解,我們要讓元素不變,所以對於每個循環節我們要染一樣的顏色,有m種顏色,c(pk)個循環節,於是每種置換的不變元素個數就是m^c(pk)。

  對於這道題,有兩種操作。

  ①旋轉。有n種置換,分別是1次旋轉1個珠子,2個,3個...n個。對於1次旋轉i個珠子,我們要求出循環節數可以先求出循環長度,一個位置置換x次之後回到原位,所以x=n*y/i,要使x盡量小且為整數那麽n*y只能是lcm(n,i),於是循環長度為lcm(n,i)/i,那麽循環節數為總長除以循環長度,n/(lcm(n,i)/i)=gcd(n,i)【n*i/gcd(n,i)=lcm(n,i)】。所以1次旋轉i個珠子的循環節數為gcd(n,i)。

  ②翻轉。對於奇偶性分類討論。

  (1)n為奇數。對於每個點作為對稱軸左右翻轉,則共n個置換,循環節數(n+1)/2。

  (2)n為偶數。

  a.對於對稱的兩個點作為對稱軸左右翻轉。n/2個置換,循環節數(n+2)/2。

  b.對於兩個點中間的空格作為對稱軸左右反轉,n/2個置換,循環節數n/2。

  則共n個置換。

  所以不論奇偶總置換數為2n,答案為sum/2n。

技術分享
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace
std; int n,m; int qp(int a,int b) { int t=1,y=a; while(b) { if(b&1)t*=y; y*=y; b>>=1; } return t; } int gcd(int a,int b){return b?gcd(b,a%b):a;} int main() { while(~scanf("%d%d",&m,&n)&&(m||n)) { int sum=0;
for(int i=1;i<=n;i++)sum+=qp(m,gcd(n,i)); if(n&1)for(int i=1;i<=n;i++)sum+=qp(m,(n+1)/2); else for(int i=1;i<=n/2;i++)sum+=qp(m,(n+2)/2)+qp(m,n/2); printf("%d\n",sum/(2*n)); } }
View Code

poj2409:Let it Bead(置換群 polya定理)