x1 到 xl就凑成了一个循环的集合,确定x1,则其它元素的值都被确定了,所以对这样一个集合有f(x1)可以为0~p-1的任意值,所以有p种选择,所以找到所有这样的集合个数num,则ans = p ^ num
如何找到集合个数呢,我用的方法是用x1推xl,xl推xl-1,直到循环,xl = k * x1 % p
现在把0加回来,对于k可以特判k=0时,有p^p-1种,k=1时,有p^p种。
当k>1时,对于x=0时,我们固定让f(x) = 1,其它值有上述算法即可。
实现
#include <iostream>#include <cstring>#include <cmath>#include <cstdio>usingnamespacestd;
typedeflonglong ll;
const ll mod = 1e9+7;
constint maxn = 1000006;
int vis[maxn];
ll powll(ll x,ll y){
ll ret = 1;
ll A = x;
while (y > 0){
if (y&1)
ret = ret * A % mod;
A = A * A % mod;
y >>= 1;
}
return ret;
}
int main(){
int p,k;
cin>>p>>k;
if (k == 0){
cout << powll(p,p-1) << "\n";
return0;
}
if (k == 1){
cout << powll(p,p) <<'\n';
return0;
}
int num = 0;
for (int i=1;i<p;i++){
if (vis[i] == 1)
continue;
num++;
int x = i;
while (vis[x] != 1){
vis[x] = 1;
x = (ll)k * (ll)x % p;
}
}
cout << powll(p,num) <<'\n';
return0;
}