题意是给你一个奇质数p和小于p的数k,求满足题目所给方程的所有映射的种数.
因为p是质数,显然x*k属于不同的模p剩余系,也就是把x=0...p-1每一个都带进去以后左边的必然是f(0) f(1) ... f(p-1)的一个排列,右边本身是f(0)...f (p-1)的一个排列,这样就可以对于
f(x1) = k*f(x2)%p,找到对应的f(x2) = k*f(x3)%p,一直迭代下去,知道发现f(xl) = k*f(x1)%p,如此就可以把这一个环路转化为 f(x1) = k^l * f(x1)%p,把右边前面的系数先模p,发现当且仅当k^l%p==1时,f(x1)的值可以任取,也就是可以有p种取法,否则f(x1)的值只能为1.
这样就很简单了,建个图,搞个环,判断系数模p.
注意特判和long long.
#include <bits/stdc++.h>
using namespace std;
#define maxn 1111111
#define mod 1000000007
long long p, k;
long long ans;
int head[maxn], cnt;
struct node {
long long from, to, next;
}edge[maxn];
long long qpow (long long a, long long b, long long m) {
if (b == 0)
return 1;
long long ans = qpow (a, b>>1, m);
ans = ans*ans%m;
if (b&1)
ans = ans*a%m;
return ans;
}
void add_edge (int from, int to) {
edge[cnt].from = from, edge[cnt].to = to, edge[cnt].next = head[from], head[from] = cnt++;
}
bool vis[maxn]; long long cur;
void dfs (int u) {
cur++;
vis[u] = 1;
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if (!vis[v]) {
dfs (v);
}
}
return ;
}
long long find_loop () {
memset (vis, 0, sizeof vis);
long long ans = 1;
for (int i = 0; i < p; i++) {
if (!vis[i]) {
cur = 0;
dfs (i);
if (qpow (k, cur, p) == 1)
ans = ans*p%mod;
}
}
return ans;
}
int main () {
while (cin >> p >> k) {
if (k == 0) {
ans = qpow (p, p-1, mod);
}
else if (k == 1) {
ans = qpow (p, p, mod);
}
else {
memset (head, -1, sizeof head);
cnt = 0;
for (int i = 0; i < p; i++) {
add_edge (k*i%p, i);
}
ans = find_loop ();
}
cout << ans << endl;
}
return 0;
}