Ploya定理+数论知识...
置换群是由旋转置换构成的,因此|G| = n
基本知识:循环的个数为gcd(i,n),循环的长度为l = n/gcd(i,n) ans = sigma(n^(gcd(n,i)-1)) 1<=i<=n
由于n很大所以需要利用欧拉函数进行优化。。。
枚举的方法有两种:
<1>将n进行质因子分解,然后根据质因子分解枚举它的约数ys,这样答案便为sigma(euler(n/ys)*n^(ys-1))
<2>枚举循环的长度l,答案为 sigma(euler(l)*n^(n/l-1))
我采用的是第一种枚举的方法,比第二种方法稍微繁琐一些,不过都很简单啦。。。
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 60000; bool is_prime[MAXN]; ll prime[MAXN]; ll facs[110], ccount[110]; ll ans, N, P; int len, cnt, x; void Init() { int i, j; len = 0; memset(is_prime, true, sizeof(is_prime)); is_prime[0] = is_prime[1] = false; prime[len++] = 2; for(i = 4; i < MAXN; i += 2) is_prime[i] = false; for(i = 3; i * i <= MAXN; i += 2) { if(is_prime[i]) { prime[len++] = i; for(j = i * i; j < MAXN; j += i) is_prime[j] = false; } } for( ; i < MAXN; ++i) if(is_prime[i]) prime[len++] = i; } ll gcd(ll a, ll b) { if(b == 0) return a; return gcd(b, a % b); } ll mul_mod(ll a, ll b, ll c) { ll ret = 0; while(b) { if(b & 1) ret = (ret + a) % c; a = a * 2 % c; b >>= 1; } return ret; } ll power_mod(ll a, ll b, ll c) { ll ret = 1; while(b) { if(b & 1) ret = mul_mod(ret, a, c); a = mul_mod(a, a, c); b >>= 1; } return ret; } void cal(ll n) { cnt = 0; memset(ccount, 0, sizeof(ccount)); for(int i = 0; i < len && prime[i]*prime[i] <= n; ++i) { if(n % prime[i] == 0) { facs[cnt] = prime[i]; while(n % prime[i] == 0) { ccount[cnt]++; n /= prime[i]; } cnt++; } } if(n > 1) facs[cnt] = n, ccount[cnt++] = 1; return ; } ll euler(ll n) { ll ret = n; for(int i = 0; i < len && prime[i]*prime[i] <= n; ++i) { if(n % prime[i] == 0) { ret = ret/prime[i]*(prime[i]-1); while(n % prime[i] == 0) { n /= prime[i]; } } } if(n > 1) ret = ret/n*(n-1); return ret; } ll power(ll a, ll b) { ll ret = 1; while(b) { if(b & 1) ret = ret * a; a = a * a; b >>= 1; } return ret; } void dfs(ll cur, int id) { if(id == cnt) { ans = (ans + euler(N/cur)*power_mod(N, cur-1, P)) % P; return ; } for(int i = 0; i <= ccount[id]; ++i) { dfs(cur*power(facs[id], i), id + 1); } return ; } int main() { //freopen("aa.in", "r", stdin); //freopen("bb.out", "w", stdout); Init(); cin >> x; while(x--) { cin >> N >> P; if(N == 1) { cout << N % P << endl; continue; } ans = 0; cal(N); dfs(1, 0); cout << ans << endl; } return 0; }