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  一样的一题目。

 

 

posted @ 2012-08-21 11:35  E_star  阅读(312)  评论(0编辑  收藏  举报