POJ - 2409 Let it Bead

3、考虑翻转的置换

旋转的有n种,相对这n种的翻转也有n种
对于奇数,翻转情况只有一个点,和它对面的中点作为对称轴,一共n种,循环节为n/2+1
对于偶数,有两种情况,一个是两个对称点构成对称轴,n/2种,循环节为n/2+1
                   一个是两个中点构成对称轴,也是n/2种,循环节为n/2
综上,所有的置换总数有2*n种
对于置换群某种置换的循环节就是考虑置换后于原先相同
比如这里的偶数两个对称点的情况,如果是6个点,那么有3条对称点的对称轴, 
翻转后相同所以3和2颜色要相同,5和6颜色要相同,1和4颜色可以不同,所以是n/2+1种颜色
image-20210721224111157
#include<iostream>
#include<algorithm>
//#include<unordered_map>
#include<fstream>
#include<iomanip>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
using namespace std;
const int mod1 = 9999973;
const int mod2 = 1e9 + 7;
typedef long long ll;
#define R register
inline ll read() {
	int f = 1;  ll x = 0; char s = getchar();
	while (!isdigit(s)) { if (s == '-')	f = -1; s = getchar(); }
	while (isdigit(s)) { x = x * 10 + s - '0'; s = getchar(); }
	return x * f;
}

//Polya定理 置换群
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}

inline ll col(ll a, ll b) {
	ll res = 1;
	while (b--) {
		res *= a;
	}
	return res;
}

int n, len;
int main() {
	while (~scanf("%d %d", &n, &len), n | len) {
		if (len == 0 | n == 0) {
			puts("0");
			continue;
		}
		
		ll ans = 0;
		int temp = len;
		for (int i = 1; i <= len; ++i) {
			ll temp = gcd(len, i);
			ans += col(n, temp);
		}

		if (len & 1) {
			ans += len * col(n, (len + 1) / 2);
		}
		else {
			ans += len / 2 * col(n, (len + 2) / 2);
			ans += len / 2 * col(n, len / 2);
		}

		ans /= (2 * len);
		printf("%lld\n", ans);
	}
	return 0;
}
posted @ 2021-07-21 22:46  wlhp  阅读(6)  评论(0)    收藏  举报