【POJ】1286.Necklace of Beads

题解

群论,我们只要找出所有的置换群的所有循环节
具体可参照算法艺术与信息学竞赛
旋转的置换有n个,每一个的循环节个数是gcd(N,i),i的范围是0到N - 1
翻转,对于奇数来说固定一个点,然后剩下的交换,循环节个数是(N - 1)/2 +1
对于偶数来说,不经过球的有N/2个,循环节个数是(N / 2)
经过球也也有N/2,循环节个数是(N / 2) + 1

代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <cstring>
#include <ctime>
#include <map>
#include <algorithm>
#include <cmath>
#define MAXN 2005
#define eps 1e-8
//#define ivorysi
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long int64;
typedef double db;
int64 pow3[35];
int N;
int gcd(int a,int b) {
	return b == 0 ? a : gcd(b,a % b);
}
void Solve() {
	if(N == 0) {puts("0");return;}
	int64 ans = 0;
	int cnt = N;
	for(int i = 0 ; i < N ; ++i) ans += pow3[gcd(N,i)];
	if(N & 1) {
		cnt += N;
		ans += pow3[(N - 1) / 2 + 1] * N;
	}
	else {
		cnt += N / 2;
		ans += pow3[N / 2] * (N / 2);
		cnt += N / 2;
		ans += pow3[N / 2 + 1] * (N / 2);
	}
	printf("%lld\n",ans / cnt);
}
int main() {
#ifdef ivorysi
	freopen("f1.in","r",stdin);
#endif
	pow3[0] = 1;
	for(int i = 1 ; i <= 24 ; ++i) pow3[i] = pow3[i - 1] * 3;
	while(scanf("%d",&N) && N != -1) {
		Solve();
	}
	return 0;
}
posted @ 2018-05-15 17:39  sigongzi  阅读(105)  评论(0编辑  收藏  举报