Codeforces Round #334 (Div. 1) B. Moodular Arithmetic

B - 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

否则

首先我们知道f(0) = 0;

我们到最小的 r 使得 k ^ r % p == 1。

那么f(x) ==  k ^ r * f(x)  == k ^ (r - 1) * f(k * x % p) == k ^ (r - 2) * f(k ^ 2 * x % p) ......... ==  f(k ^ r * x % p) == f(x % p) == f(x)

所以我们可以知道我们挑选了一个f(x)的值之后,我们就能确定 r 个函数的值。

所以我们只要挑(p - 1) / r 个值就能确定全部函数, 因为 k ^ (p - 1) % p == 1    k ^ r % p == 1

所以r一定能整除(p - 1)。 所以答案就是 p ^ ((p - 1) / r);

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int, pair<int,int> >

using namespace std;

const int N = 2e5 + 10;
const int M = 10 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;

LL fastPow(LL a, LL b) {
    LL ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod; b >>= 1;
    }
    return ans;
}


LL p, k;
int main() {

    scanf("%lld%lld", &p, &k);
    if(k == 0) {
        printf("%lld\n", fastPow(p, p - 1));
    } else if(k == 1) {
        printf("%lld\n", fastPow(p, p));
    } else {
        int m = 1;
        for(LL j = k; j != 1; j = j * k % p) {
            m++;
        }
        printf("%lld\n", fastPow(p, (p - 1) / m));
    }
    return 0;
}
/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/9139254.html