题意: n个珠子染n种颜色,各种颜色数量不限,n <= 10^9,输出方案数模p.
满足gcd(n,x) = k的x有phi(n/k)个,即polya中置换节点数为k的置换有phi(n/k)个,所以只需枚举置换节点数i 1~根号n, 且 i | n 为能出现的节点长度, 同时注意到 n/i 也是可行的
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int n;
int mod;
int ans;
int Eular(int a) {
int ret = 1;
for (int i = 2; i * i <= a; i++) if (a % i == 0) {
ret *= i - 1;
a /= i;
while (a % i == 0) {
ret *= i;
a /= i;
}
}
if (a > 1) ret *= a - 1;
return ret % mod;
}
int qpow(int a, int b) {
int ret = 1;
a %= mod;
while (b) {
if (b & 1) ret = (ret * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ret;
}
int main()
{
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &mod);
ans = 0;
for (int i = 1; i * i <= n; i++) if (n % i == 0) {
ans = (ans + (qpow(n, n / i - 1) * Eular(i)) % mod) % mod;
if (n / i != i)
ans = (ans + (qpow(n, i - 1) * Eular(n / i)) % mod) % mod;
}
printf("%d\n", ans);
}
return 0;
}