题解
群论,我们只要找出所有的置换群的所有循环节
具体可参照算法艺术与信息学竞赛
旋转的置换有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
",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;
}