题意:
n个球围成一个圈,每个球是白色或黑色,要求不能有连续的黑球相邻,并且旋转同构,求有多少种合法方案。
思路:
设不考虑旋转同构时,
n
个球的方案为
同构时需要使用burnside引理。
考虑循环位移,每个元素可以顺时针移
1,2,3,...n
个元素设为,设
F(k)
为
n
个元素位移
然后推导下不动点,考虑
F(i)
,就是一个元素不断位移i次,最后回到i,路上经过的元素就是一个置换群,经过的点数其实就是
n/gcd(i,n)
,那么一共有
n/(n/gcd(i,n))
个,即
gcd(i,n)
个不同的置换群,那么
C(F(i))=f(gcd(i,n))
。
枚举n的约数即可算答案。
//
// main.cpp
// 5868
//
// Created by 翅膀 on 16/9/15.
// Copyright © 2016年 kg20006. All rights reserved.
//
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
ll euler(ll n) {
ll res = n, a = n;
for(ll i = 2; i*i <= a; i++){
if(a%i == 0){
res = res/i*(i-1);
while(a%i == 0) a /= i;
}
}
if(a > 1) res = res/a*(a-1);
return res;
}
struct mat{
ll r[2][2];
mat(){ memset(r, 0, sizeof(r)); }
mat operator *(const mat& z) {
mat res;
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
for(int k = 0; k < 2; ++k) {
res.r[i][j] += r[i][k]*z.r[k][j];
res.r[i][j] %= mod;
}
}
}
return res;
}
}a, b;
ll f(ll k) {
if(k == 1) return 1;
else if(k == 2) return 3;
else if(k == 3) return 4;
k -= 3;
mat res, aa = b;
res.r[0][0] = res.r[1][1] = 1;
while(k) {
if(k&1) res = res*aa;
aa = aa*aa;
k >>= 1;
}
res = res*a;
return res.r[0][1];
}
ll qpow(ll a, ll k) {
ll res = 1;
while(k) {
if(k&1) res = (res*a)%mod;
a = (a*a)%mod;
k >>= 1;
}
return res;
}
int main(int argc, const char * argv[]) {
a.r[0][0] = 3, a.r[0][1] = 4, a.r[1][0] = 1, a.r[1][1] = 3;
b.r[0][0] = b.r[0][1] = b.r[1][0] = 1;
ll n;
while(scanf("%lld", &n) != EOF) {
if(n == 1) { printf("2\n"); continue; }
ll ans = 0;
for(ll k = 1; k*k <= n; ++k) {
if(n%k == 0) {
ans += f(k)*euler(n/k)%mod;
if(k*k != n) ans += f(n/k)*euler(k)%mod;
ans %= mod;
}
}
ans = ans*qpow(n, mod-2)%mod;
printf("%lld\n", ans);
}
return 0;
}