传送门:点击打开链接
题意:告诉你p和k,其中(0<=k<=p-1),x属于{0,1,2,3,....,p-1},f函数要满足f(k*x%p)=k*f(x)%p,f(x)的范围必须在[0.p-1]内,问这样的f函数有多少个
思路:首先这个怎么看都跟循环节有关。。那么怎么找到循环节呢。。
首先找k为0的情况,可以发现此时答案就是p^(p-1)
然后k为1的情况,答案就是p^p
如果k>=2
很明显可以发现f(0)=0是肯定的
假设k^r%p=1,r是最小满足这个条件的正整数
那么f(x),因为f(x)在[0,p-1]内,
所以f(x)=k^r*f(x)%p=k^(r-1)*f(k*x%p)=k^(r-2)*f((k^2)*x%p)=k^(r-3)*f((k^3)*x%p)=....
=k^(r-r)*f((k^r)*x%p)=f((k^r)%p*x%p)=f(x%p)=f(x)
可以发现,在上面这个式子中,这r个x组成了一个环,这个环的数字都是相等的
本来x的范围中有p个数字,除去x=0的情况,还有p-1个数字。
又因为k^(p-1)%p=1,k^r%p=1,所以r肯定是p-1的因数
所以,p-1是肯定能整除r的,那么剩下的p-1个数字就能分成(p-1)/r个环
对于每个环上的数字都应该相同,这个数字有p种情况,即[0,p-1],一共有(p-1)/r个环
所以答案是p^((p-1)/r)
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; const int MX = 100000 + 5; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int p, k; int solve() { int e; if(k == 0) e = p - 1; else if(k == 1) e = p; else { e = 1; LL s = k; while(s != 1) { e++; s = s * k % p; } e = (p - 1) / e; } LL ans = 1; for(int i = 1; i <= e; i++) { ans = ans * p % mod; } return ans; } int main() { scanf("%d%d", &p, &k); printf("%d\n", solve()); return 0; }