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

Color necklace 1

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

General idea

A necklace, then there are n colors for you to paint on n beads.
(It is not necessary to use all the colors)
Then ask you how many kinds of necklaces are essentially different.

The essence is different, no matter how you choose the two necklaces, they cannot overlap (that is, the color for the position is the same).

Ideas

We see the essential difference, and then it transfers some states. Naturally, we think of Burnside's lemma and Polya's theorem.

What is it for?
It is for things that can be transferred in this state, and then being able to transfer means that the essence is the same, and it is used to find how many essentially different states there are.

Then the thing that can make the state transition is called permutation.
f = (a 1, a 2,..., an) f=(a_1,a_2,...,a_n)f=(a1,a2,...,an) This permutation meansiii can be transferred toai a_iai

Then you will know that by doing this, one or more loops will appear, that is, a certain point can always jump in this loop.
Those cycles are disjoint.

Burnside's lemma is to solve the number of essentially different states that can exist when there are multiple permutations.
Here is the formula of Burnside's Lemma:
L = 1 ∣ G ∣ ∑ r ∈ G c 1 (r) L=\dfrac{1}{|G|}\sum\limits_{r\in G}c_1(r )L=G1rGc1(r)

GG G is the permutation group, which contains all permutations given. c 1 (r) c_1(r)c1( r ) is replacingrrThe number of self-directed transfers to their own state in r .

As for this proof, I am too good to prove it. You're done with it!

Then look at Polya's theorem, which is the algorithm used for this problem.
It's what multi-color situations can be handled.

In the previous lemma, you need to list all the states, but if there are more colors, you can't express all the states, you need to use this algorithm.

The formula is this:
L = 1 ∣ G ∣ ∑ r ∈ G mc (r) L=\dfrac{1}{|G|}\sum\limits_{r\in G}m^{c(r)}L=G1rGmc(r)

Where c (r) c(r)The meaning of c ( r ) is no longer the same, that is,rrThe number of cycles in r permutation.
It mainly means that each cycle can choose any color, and then the color of the points in the cycle is the same, and then it becomes like this in the middle.

m m m is the number of colors.

Then you list the permutation rk r_krkIs (k + 1, k + 2,..., N, 1, 2,..., K) (k+1,k+2,...,n,1,2,...,k )(k+1,k+2,...,n,1,2,...,k ) .
It can be known thatc (r) = gcd ⁡ (k, n) c(r)=\gcd(k,n)c(r)=gcd(k,n) ∣ G ∣ = n |G|=n G=n

But it is still not very good, we consider continuing to optimize.
L = 1 n ∑ d ∣ n (nd ∑ [d = gcd ⁡ (k, n)]) L=\dfrac{1}{n}\sum\limits_{d|n}(n^d\sum[d =\gcd(k,n)])L=n1dn(nd[d=gcd(k,n ) ] )
(because it isgcd ⁡ \gcdg cd , so we can putgcd ⁡ \gcdThe same value of g cd is extracted, the previous summation is a single contribution, and the inside is to find out how many have the same value)
L = ∑ d ∣ n (nd − 1 ∑ [1 = gcd ⁡ (kd, nd)]) L=\sum\limits_{d|n}(n^{d-1}\sum[1=\gcd(\dfrac{k}{d},\dfrac{n}{d})] )L=dn(nd1[1=gcd(dk,dn) ] )
Then you will findgcd ⁡ \gcdThe right side of g cd has nothing to do with the loop inside, and it isgcd ⁡ \gcdThe two coprime in g cd naturally think of Euler's function.
L = ∑ d ∣ n (nd − 1 φ (nd)) L=\sum\limits_{d|n}(n^{d-1}\varphi(\dfrac{n}{d}))L=dn(nd1φ(dn))

Then you can do it.

Code

#include<cstdio>
#define ll long long

using namespace std;

int T, n;
ll mo, ans, su[35001];
bool ns[35001];

void get_su() {
    
    //欧拉筛筛出素数
	ns[1] = ns[0] = 1;
	for (int i = 2; i <= 35000; i++) {
    
    
		if (!ns[i]) {
    
    
			su[++su[0]] = i;
		}
		for (int j = 1; j <= su[0] && i * su[j] <= 35000; j++) {
    
    
			ns[i * su[j]] = 1;
			if (i % su[j] == 0) break;
		}
	}
}

ll ksm(ll x, ll y) {
    
    //快速幂
	ll re = 1;
	while (y) {
    
    
		if (y & 1) re = (re * x) % mo;
		x = (x * x) % mo;
		y >>= 1;
	}
	return re;
}

ll phi(ll now) {
    
    //算phi值
	ll re = now;
	for (ll i = 1; su[i] * su[i] <= now; i++)
		if (now % su[i] == 0) {
    
    
			re = re / su[i] * (su[i] - 1);
			while (now % su[i] == 0) now /= su[i];
		}
	if (now != 1) re = re / now * (now - 1);
	return re;
}

int main() {
    
    
	get_su();
	
	scanf("%d", &T);
	for (int times = 1; times <= T; times++) {
    
    
		scanf("%d %lld", &n, &mo);
		
		ans = 0;
		for (int i = 1; i * i <= n; i++) {
    
    //枚举因子
			if (n % i == 0) {
    
    
				//我们上面弄出来的公式
				ans = (ans + ksm(n, i - 1) * phi(n / i) % mo) % mo;
				if (i * i != n)
					ans = (ans + ksm(n, (n / i) - 1) * phi(n / (n / i)) % mo) % mo;
			}
		}
		
		printf("%lld\n", ans);
	}
	
	return 0;
}

Guess you like

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