数论 Codeforces604D Moodular Arithmetic

传送门:点击打开链接

题意:告诉你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;
}


你可能感兴趣的:(数论 Codeforces604D Moodular Arithmetic)