Reference to Http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove template
For each dye, there is an equivalent group, such as rotation, flipping, etc. We convert each transformation into a permutation group, and the equivalent dyeing schemes are obtained by permutation groups.
Finally, the number of non-equivalent staining schemes we asked for.
In the Burnside theorem, it is given that in each permutation group it is also the number of the equivalent group divided by the number of permutation groups, that is, the non-equivalent number of shading equals the chromatic average of the constant under displacement in the permutation group.
We take POJ 2409 let it bead as an example http://poj.org/problem?id=2409
n A ring of items, M color. Very basic question.
So how many permutation groups are there, and obviously the rotation is equivalent, then the rotation is 0 degrees, which is a total of n rotations.
For each rotation of the equivalent amount of how to calculate it. We find that there are several cyclic sections in each rotation permutation, such as 1,3,5 is a circular section, then rotated once, 1th to 3rd, and 3rd to 5th, obviously the color of a loop section must be the same. There are m color choices, the question is converted into how many follow links. For rotations there is obviously gcd (i,n). So as long as I can enumerate, this is the Polya theorem.
And in the flip, if n is odd, there is obviously an item is fixed, the other 22 symmetry, color is the same. N/2+1 a cycle section,
If n is an even number, divided into two cases, one is the symmetry axis but the item, then all items 22 corresponding, N/2 cycle section, the other is a symmetrical axis through two items, (n-2)/2+1+1 a follow-up link. For each cycle section there is a choice of M colors.
#include <iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#defineN 100005#defineINF 1<<29#defineMOD 2007#defineLL Long Longusing namespacestd; ll GCD (ll A,ll b) {returnb==0? A:GCD (b,a%b);} ll Pow (ll A,intb) {LL ret=1; while(b) {if(b&1) ret=ret*A; A=a*A; b>>=1; } returnret;} LL Polya (intNintm) {LL sum=0; //enumeration of n rotations for(intI=1; i<=n;i++) //each cycle section is an optional m color//A total of gcd (N,i) A follow-up linksum+=Pow (M,GCD (n,i)); if(n&1) //if it is odd, the number of circular sections in all locations is n/2+1Sum+=n*pow (m,n/2+1); Else //Otherwise you'll have to divide the odd couple, halfsum+=n/2*pow (m,n/2) +n/2*pow (m,n/2+1); returnsum/2/N;}intn,m;intMain () { while(SCANF ("%d%d", &m,&n)!=eof&&n+m) {printf ("%lld\n", Polya (n,m)); } return 0;}
Enumeration rotation can be very time-consuming for n if it is very large. Next, you can have an optimization
We enumerate the length of the cyclic section L, then the number of circular section is n/l, must be N of the approximate only line.
So D=N/L=GCD (I,n), for each L, we need to find out how many I satisfy the left side of the equation.
Make I=D*T,GCD (d*t,l*d) =d, to the left of the formula is established, obviously gcd (t,l) ==1, otherwise greatest common divisor is not d.
Then for any t satisfies with l coprime, it is the Euler function value of L
This allows enumeration of L,∑ (PHI (L) * m^ (n/l))% P (L is the enumeration value) within the complexity of sqrt (n).
#include <iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#defineN 100005#defineINF 1<<29#defineMOD 2007#defineLL Long Longusing namespacestd; ll GCD (ll A,ll b) {returnb==0? A:GCD (b,a%b);} ll Eular (ll N) {ll ret=1; for(intI=2; i*i<=n;i++){ if(n%i==0) {n/=i; RET*=i-1; while(n%i==0) {n/=i; RET*=i; } } } if(n>1) ret*=n-1; returnret;} ll Pow (ll A,ll b) {LL ret=1; while(b) {if(b&1) ret=ret*A; A=a*A; b>>=1; } returnret;} LL Polya (intNintm) {LL sum=0; inti; for(i=1; i*i<n;i++) if(n%i==0) {sum+=eular (i) *pow (m,n/i); Sum+=eular (n/i) *Pow (m,i); } if(i*i==n) Sum+=eular (i) *Pow (m,i); if(n&1) Sum+=n*pow (m,n/2+1); Elsesum+=n/2*pow (m,n/2) +n/2*pow (m,n/2+1); returnsum/2/N;}intn,m;intMain () { while(SCANF ("%d%d", &m,&n)!=eof&&n+m) printf ("%lld\n", Polya (n,m)); return 0;}
Source Code:
#include <iostream>#include<cstring>#include<cstdio>#include<cmath>#defineMOD 1000000007#defineLL Long Longusing namespacestd;intprime[ -]={2,3,5,7, One, -, -, +, at, in, to,Panax Notoginseng, A, +, -, -, -, A, the, in, the, -, the, the, the,101},cnt= -; LL n,m; ll Eular (ll N) {ll sum=1; for(inti =2; I <= sqrt (1.0+ N); ++i)if(n% i==0) {sum*= (I-1); N/=i; while(n% i = =0) {sum*=i; N/=i; } } if(N >1) Sum*= (n1); returnSum%MOD;} ll Pow (ll A,ll b) {LL ret=1; while(b) {if(b&1) ret= (ret*a)%MOD; A= (a*a)%MOD; b>>=1; } returnret;} ll Polya () {ll sum=0, I; for(i=1; i*i<n;i++){ if(n%i==0) {sum= (Sum+eular (i) *pow (m,n/i))%MOD; Sum= (Sum+eular (n/i) *pow (m,i))%MOD; } } if(i*i==N) Sum= (Sum+eular (i) *pow (m,i))%MOD; if(n&1) Sum= (Sum+n*pow (m,n/2+1))%MOD; Elsesum= (sum+n/2* (Pow (m,n/2) +pow (m,n/2+1)))%MOD; return(Sum*pow (2*n,mod-2))%MOD;}intMain () {LL T,cas=0; scanf ("%i64d",&t); while(t--) {scanf ("%i64d%i64d",&m,&N); printf ("Case #%i64d:%i64d\n",++Cas,polya ()); } return 0;}
HDU 3923 Invoker "Naked Polya theorem"