彩色项链2
题目链接:ybt金牌导航8-5-2
题目大意
m 个颜色的珠子,可以放 n 个组成项链,问你能做出多少个不重复的。
重复是当项链可以通过旋转和沿中轴线翻转可以完全相同。
思路
这道题跟——>这一道题<——差不多。
因为它 (n,m) 可能不一样,你会发现你之前用的化公式的方法就不能直接用上去。
但是它范围很小,那我们就暴力搞,那这个也不是问题。
但是它还有沿中轴线翻转的操作。
那我们也往 Polya 定理的方向上考虑。
那你遇到这种中间翻转的(比如回文串),就想到了奇偶分类。
如果长度是奇数,那就一定中轴线一定要碰到一个点(也只能碰到一个),那就有 ((n-1)/2) 个两个点的循环 (1) 个一个点的循环,那就是 ((n+1)/2) 个循环。然后每个点都可以作为被中轴线碰到的点,那就一共有 (n) 个这样的置换。
如果长度是偶数,那你会想到可以分两种可能:中轴线什么都碰不到,中轴线碰到了两个点。
那两个都各有 (n/2) 个这样的置换,什么都碰不到的循环有 (n/2) 个,碰到两个的循环有 (2+(n-2)/2=(n+2)/2) 个。
那按着这么算就好了。
(记得总的置换个数有 (2 imes n) 个)
代码
#include<cstdio>
#define ll long long
using namespace std;
int n, m;
ll ans;
void csh() {
ans = 0;
}
ll gcd(ll x, ll y) {//求gcd
if (!y) return x;
return gcd(y, x % y);
}
ll ksm(ll x, ll y) {//快速幂
ll re = 1;
while (y) {
if (y & 1) re = re * x;
x = x * x;
y >>= 1;
}
return re;
}
int main() {
scanf("%d %d", &m, &n);
while (m || n) {
csh();
for (int i = 1; i <= n; i++) {
ans += ksm(m, gcd(i, n));//旋转
}
if (n & 1) ans += n * ksm(m, (n + 1) / 2);//沿中轴线翻转(分奇偶讨论)
else ans += n / 2 * ksm(m, n / 2) + n / 2 * ksm(m, (n + 2) / 2);
ans /= n * 2;
printf("%lld
", ans);
scanf("%d %d", &m, &n);
}
return 0;
}