POJ2154 Color 【Polya定理 + 欧拉函数】

题目

Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of the necklace can be produced. You should know that the necklace might not use up all the N colors, and the repetitions that are produced by rotation around the center of the circular necklace are all neglected.

You only need to output the answer module a given number P.

输入格式

The first line of the input is an integer X (X <= 3500) representing the number of test cases. The following X lines each contains two numbers N and P (1 <= N <= 1000000000, 1 <= P <= 30000), representing a test case.

输出格式

For each test case, output one line containing the answer.

输入样例

5
1 30000
2 30000
3 30000
4 30000
5 30000

输出样例

1
3
11
70
629

题解

题意:

用n种颜色染n个点的环,问有多少本质不同的染法

Polya定理##

我们设置换群为G,\(c(i)\)表示置换i的循环节个数,m为色数,L为答案
\(L = \frac{1}{\mid G \mid} \sum_{i=1}^{s} m^{c(i)}\)

本题有n个置换,置换i循环节个数为\(gcd(n,i)\)
那么我们有:
\(ans = \frac{1}{n} \sum_{i=1}^{n} n^{gcd(n,i)}\)
\(\qquad = \frac{1}{n} \sum_{d|n} n^d \sum_{i=1}^{n}[gcd(n,i)==1]\)
\(\qquad = \sum_{d|n} n^{d-1} \sum_{i=1}^{n/d}[gcd(n/d,i)==1]\)
\(\qquad = \sum_{d|n} n^{d-1} \phi(n/d)\)

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
	while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
	return out * flag;
}
int P,prime[maxn],primei;
bool isn[maxn];
void init(){
	for (int i = 2; i < maxn; i++){
		if (!isn[i]) prime[++primei] = i;
		for (int j = 1; j <= primei && i * prime[j] < maxn; j++){
			isn[i * prime[j]] = true;
			if (i % prime[j] == 0) break;
		}
	}
}
int qpow(int a,int b){
	int ans = 1;
	for (; b; b >>= 1,a = (LL)a * a % P)
		if (b & 1) ans = (LL)ans * a % P;
	return ans;
}
int phi(int n){
	int ans = n;
	for (int i = 1; prime[i] * prime[i] <= n; i++){
		int p = prime[i];
		if (n % p == 0){
			ans = ans - ans / p;
			while (n % p == 0) n /= p;
		}
	}
	if (n > 1) ans = ans - ans / n;
	return ans % P;
}
int cal(int n,int d){
	return qpow(n,d - 1) * phi(n / d) % P;
}
int main(){
	init();
	int T = read(),n,ans;
	while (T--){
		n = read(); P = read(); ans = 0;
		for (int i = 1; i * i <= n; i++){
			if (n % i == 0){
				ans = (ans + cal(n,i)) % P;
				if (i * i != n) ans = (ans + cal(n,n / i)) % P;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

posted @ 2018-01-19 19:31  Mychael  阅读(159)  评论(0编辑  收藏  举报