pku 1286 Necklace of Beads polya定理

http://poj.org/problem?id=1286

题意:

3种颜色对一个有n个顶点的圈着色,问有多少种不同的着色方法。对于通过旋转或者翻转得到的相同的着色视为一种;

思路:

Polya定理

    设有n个对象,G是这n个对象上的置换群,用m种颜色涂染这n个对象,每个对象涂染一种颜色,问有多少种染色方案?一种染色方案在群G的作用下变为另一种方案,则这两种方案当作是一种方案。

    方案数为

因为这里的有旋转与翻转两种所以|G|的个数为2*n |G|表示置换群的个数

View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <string>



#define CL(a,num) memset((a),(num),sizeof(a))

#define iabs(x)  ((x) > 0 ? (x) : -(x))



#define maxn 50004

#define ll __int64

#define inf 0x7f7f7f7f

#define MOD 100000007

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

using namespace std;



ll gcd(ll a,ll b)

{

    if (b == 0) return a;

    else return gcd(b,a%b);

}

ll Pow(ll a,ll b)

{

    ll s = 1;

    for (int i = 1; i <= b; ++i) s *= a;

    return s;



}

ll polya(ll c,ll n)

{

    if (n == 0) return 0;

    ll sum = 0;

    for (int i = 1; i <= n; ++i)

    sum += Pow(c,gcd(i,n));



    if (n&1) sum += n*Pow(c,n/2 + 1);

    else

    {

        sum += (n/2)*Pow(c,n/2) + (n/2)*Pow(c,n/2 + 1);

    }

    return sum/2/n;

}

int main()

{

    ll n;

    while (~scanf("%I64d",&n))

    {

        if (n == -1) break;

        printf("%I64d\n",polya(3,n));

    }

    return 0;

}

 

 http://poj.org/problem?id=2409  一样的一题目。

 

 

你可能感兴趣的:(pku)