[Ybt gold medal navigation 8-5-2] color necklace 2

Color necklace 2

Topic link: ybt gold medal navigation 8-5-2

General idea

For m beads of colors, you can put n to form a necklace, and ask you how many unique ones you can make.
The repetition is when the necklace can be rotated and flipped along the central axis can be exactly the same.

Ideas

This question is now -> The questions <- almost.

Because it n, mn, mn,m may be different, you will find that the method of formulating the formula you used before cannot be used directly.
But its scope is very small, so we will do it violently, then this is not a problem.

But it also has the operation of flipping along the central axis.
Then we also consider the direction of Polya theorem.
Then when you encounter this kind of intermediate flipping (such as palindrome), you think of parity classification.

If the length is odd, then the central axis must touch a point (and only one), then there is (n − 1) / 2 (n-1)/2(n1 ) / 2 two-point loop1 1. 1 cycle a point, that is,(n + 1) / 2 ((n+1 ) / 2 cycles. Then each point can be used as the point touched by the central axis, so there is a total ofnnn such permutations.

If the length is an even number, then you will think of two possibilities: the central axis will not touch anything, and the central axis will touch two points.
Both of those have n / 2 n/2n / 2 such permutations, there aren / 2 n/2cycles that can't be touchedn / 2 , the loop that meets two is2 + (n − 2) / 2 = (n + 2) / 2 2+(n-2)/2=(n+2)/22+(n2)/2=(n+2 ) / 2 pcs.

Then just press it like this.
(Remember that the total number of permutations is 2 × n 2\times n2×n )

Code

#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\n", ans);
		
		scanf("%d %d", &m, &n);
	}
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/114154083