polay定理总结
參考資料:polay定理
感覺近期一直easy遇見這樣的題目....... 略微復雜一點的就不太會
先是一個總結出來的定理:
用一個最簡單的樣例來說明
對2*2的方陣用黑白兩種顏色涂色,問能得到多少種不同的圖像?經過旋轉使之吻合的兩種方案,算是同一種方案。
設G={p1,p2,…,pg}是Ω上的一個置換群比方置換群G={轉0°。轉90°,轉180°,轉270°}
C(pk)是置換pk的循環的個數 ?
G1置換{轉0° ?}的循環節是4。 {(1),(2),(3),(4)}
G2置換{轉90° }的循環節是1, {(4,3,2,1)}
G3置換{轉180°}的循環節是2, {(1,3),(2,4)}
G4置換{轉270°}的循環節是1。 {(1,2,3,4)}
用M中的顏色對Ω中的元素著色,
著色方案數為 L = 1/|G|*[c1(p1)+c1(p2)+c1(p3)+...c1(p[g])]?
? ? ? ?= 1/|G|*[m^c(p1)+m^c(p2)+m^c(p3)+...m^c(p[g])]
|G|為置換的總個數,m顏色數?
c1(pi)指置換pi的不動點的數目(既循環節為1的點數)
明顯四個數分別為 16 2 4 2?
L = 1/|G| * [16 + 2 + 4 + 2] = 6
c(pi)指的是置換pi的循環個數。
L = ?1/|G| *[ 2^4 + 2^1 + 2^2 + 2^1 ] = 6?
先來一個簡單的題目:
poj 2409 :?http://poj.org/problem?
id=2409
題目大意:?
一家項鏈公司生產手鐲。n顆珠子形成一個環,用m種顏色給n顆珠子染色,就得到了各種各樣的手鐲。可是,經過旋轉和翻轉使之吻合的算同一種方案。
比如,當用2種顏色對5顆珠子進行染色的方案數為8。
題目解法:
一: 旋轉 (比方說是有n個珠子。每次能夠旋轉的角度就是360/n)
二: 翻轉 (考慮對稱軸。奇數個珠子,那每次對稱軸能夠穿過一個珠子。則一共同擁有n個對稱軸)
偶數個珠子,每一個對稱軸穿過的是兩個珠子,一共同擁有n/2個對稱軸,或者說每一個對稱軸不穿過珠子,這種對稱軸也是n/2個
所以綜上來說無論是奇數或者偶數。其變化方式都是有2*n種翻轉。
能夠證明的是每個翻轉其循環節各自是gcd(i,n) ?0<i<=n
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> using namespace std;int gcd(int a,int b){return b==0?a:gcd(b,a%b); }long long rotate(int c,int n){ //旋轉 旋轉 (360/n) * i 度long long sum=0;for(int i=1;i<=n;i++) sum+=pow(c*1.0,gcd(n,i)); //每次旋轉的循環節是gcd(n,i)return sum; }long long turn(int c,int n){ //翻轉long long sum=0;if(n%2)sum+=n*pow(c*1.0,(n+2)/2); //奇數則對稱軸都是穿過一個珠子 一共n個 每一個置換的循環節是n/2+1elsesum+=n/2*(pow(c*1.0,n/2)+pow(c*1.0,(n+2)/2)); //偶數則穿過珠子或者不穿過珠子 各自是n/2 個 循環節是n/2+1 和 n/2 能夠用下面公式算出return sum; }void polya(int c,int n){int i,j;long long sum=0;sum+=rotate(c,n);sum+=turn(c,n);printf("%lld\n",sum/(2*n)); }int main() {int n,m;while(scanf("%d%d",&n,&m),n||m){polya(n,m);}return 0; }
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0)#define eps 1e-7 #define INF 0x7FFFFFFF #define LLINF 0x7FFFFFFFFFFFFFFF #define seed 1313131 #define MOD 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1//求置換的循環節,polya原理 //perm[0..n-1]為0..n-1的一個置換(排列) //返回置換最小周期,num返回循環節個數 #define MAXN 1000int gcd(int a,int b){return b?gcd(b,a%b):a; }int polya(int* perm,int n,int& num){int i,j,p,v[MAXN]={0},ret=1;for (num=i=0;i<n;i++)if (!v[i]){for (num++,j=0,p=i;!v[p=perm[p]];j++)v[p]=1;ret*=j/gcd(ret,j);}return ret; }int main (){int perm1[6]={0,5,4,3,2,1};int perm2[6]={1,0,5,4,3,2};int num;cout<<polya(perm2,6,num)<<endl;cout<<num<<endl; }
版權聲明:本文博客原創文章。博客,未經同意,不得轉載。
總結
- 上一篇: Notepad++去除代码行号的几种方法
- 下一篇: IIS如何配置可以下载APK、IPA文件