您的位置:首页 > 其它

POJ 1286 polya组合数定理

2016-04-29 18:51 253 查看

题目

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj