CF 603B 数学,同余

题目大意:给出方程f(kx%p)=kf(x)%p ,问在集合A->B上不同的映射函数f 有几种,其中A=B={0,1,2..p-1},p为素数(除了2),k为小于p的一个常数


思路: 因为f(kx%p) , 将x = kx 带入得f(kx%p) = f(k*kx%p),所以乘以k除以k相等,所以f(x%p) = f(kx%p) , 又因为f(kx%p)=kf(x)%p  , 所以f(x%p)  = k*k*k*k……%p,肯定存在循环节,找到循环节m。起始项有p个,每个都有p/m个环即不同的组成方式。所以结果为p^(p/m), 特判k=0和k=1的情况即可。


#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
#include <iostream>

using namespace std;
#define maxn 1000003
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL __int64
int p , k;

LL powe(LL n , LL m )
{
    LL ans = 1;
    while(m > 0)
    {
        if(m&1) ans = (ans * n) % MOD;
        m >>= 1;
        n = (n * n) % MOD;
    }
    return ans;
}

int main()
{
    while(scanf("%d %d" , &p , &k) != EOF)
    {
        LL m = 1 , x = 1;
        for(int i = 1 ; i <= p ; i ++)
        {
            x = x*k % p;
            if(x == 1)break;
            m++;
        }
      //  cout << m << endl;
        LL ans = 0;
        if(k == 0) ans = powe(p , p-1);
        else if(k == 1) ans = powe(p , p);
        else ans = powe(p , (p) / m);
        printf("%I64d\n" ,ans);
    }
    return 0;
}


你可能感兴趣的:(CF 603B 数学,同余)