POJ 1286 polya组合数定理

题目

Necklace of Beads
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 7528 Accepted: 3134
Description

Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 24 ). If the repetitions that are produced by rotation around the center of the circular necklace or reflection to the axis of symmetry are all neglected, how many different forms of the necklace are there?

Input

The input has several lines, and each line contains the input data n.
-1 denotes the end of the input file.
Output

The output should contain the output data: Number of different forms, in each line correspondent to the input data.
Sample Input

4
5
-1
Sample Output

21
39

题意

有三种颜色的珠子n个,用这个n个珠子围成一个圆形的项链。两个项链认为是不同的单且仅当这两个项链不能通过旋转或者沿某一轴翻转成和原来的项链一样。

题解

此题是poj2409的弱化版
polya定理运用群论(置换群,对称群)给出一个公式来计算不同变换方式的组合数
《算法艺术和信息学竞赛》上写到
设G是p个对象的一个置换群,用k个颜色涂染这p个对象,若有一种染色方案在群G的作用下变为另一种方案,则这两个方案是同一种方案,这样不同的染色方案数为:

c(f)为置换群f的循环节
本题直接用模板就行了。关于polya更深的理解可以看《组合数学》这本书的记录

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <string>
#include <set>
#include <cmath>
#include <map>
#include <queue>
#include <sstream>
#include <vector>
#include <iomanip>
#define m0(a) memset(a,0,sizeof(a))
#define mm(a) memset(a,0x3f,sizeof(a))
#define m_1(a) memset(a,-1,sizeof(a))
#define f(i,a,b) for(i = a;i<=b;i++)
#define fi(i,a,b) for(i = a;i>=b;i--)
#define lowbit(a) ((a)&(-a))
#define FFR freopen("data.in","r",stdin)
#define FFW freopen("data.out","w",stdout)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef long double ld;
const ld PI = acos(-1.0);

using namespace std;
#define SIZE ( )

ll gcd(ll a, ll b) {
    if (!b) {
        return a;
    } else {
        gcd(b, a%b);
    }
}

ll mod_pow(ll x, ll n) {
    ll res = 1;
    while (n>0) {
        if (n & 1) res = res*x;
        x = x*x;
        n >>= 1;
    }
    return res;
}

int main() {
    //ios_base::sync_with_stdio(false); cin.tie(0);
    int n;
    while (~scanf("%d",&n)&&n!=-1) {
        if (!n) {
            printf("0\n");
            continue;
        }
        ll ans = 0;
        int i;
        f(i, 1, n)
            ans += mod_pow(3, __gcd(n, i));
        ans /= n;
        ll tem = mod_pow(3, (n + 1) >> 1);
        if (n & 1)
            printf("%I64d\n", (ans + tem) >> 1);
        else
            printf("%I64d\n", ((tem * 4 / 2) + ans)>>1);

    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值