Codeforces 603B - Moodular Arithmetic 数论 应用群的基本性质

题意

  • 一类函数,他们的定义域是{0,1,..,P-1},值域也是这个,但不一定是一一映射
  • 其中p是奇数,且是质数
  • 就是给你p和k,问你满足,给定的等式的函数有多少个,k是等式中的参数
  • 等式是f(k * x % p) = k * f(x) % p。
  • k的范围是0~p-1,p<10^6

思路

  • 这题主要应用了群的性质,除去0的模p运算,是一个群
  • 先不考虑0,让x和k都非0
  • 我们先证明k * x % p的值各不相同,且会包含全部的1~p-1
  • 假设k * x1 % p = k * x2 % p ,且x1 != x2
  • 在群中,所以每个元素有逆元,那么k^-1 * k * x1 %p = k^-1 * k * x2 %p
  • 所以x1 = x2,由此得证。
  • 利用不停迭代,可以得出下面的关系:
  • 任取x1,有f(x1) = k*f(x2)%p = k^2 * f(x3) % p = … = k^l * f(x1)
  • 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>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int 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";
        return 0;
    }
    if (k == 1){
        cout << powll(p,p) <<'\n';
        return 0;
    }
    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';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值