• 原根


    定义:

      在mod P 域中,若 (a^i)!=(a^j) (0<=i,j<φ(p)) 则称其a为P的原根。

    说人话就是:

      如果g是P的原根,那么g的(1…P-1)次幂mod P的结果一定互不相同

    这个很重要,说明 a 是 一个群的生成元

     那么我们如何求原根呢?

     我们求原根,往往只要找一个就行了,那么我们考虑暴力

      首先,原根的数量并不少,P的原根有φ(φ(p))个,我们可以暴力枚举 i(from 2 to p-1)去检查每个i是否合法。

     我们发现chenk 要O(P)的时间复杂度,太大了。

      有一个方便的方法就是,求出x-1所有不同的质因子p1,p2…pm,对于任何2<=a<=x-1,判定a是否为x的原根,只需要检验a((x-1)/p1),a((x-1)/p2),…a((x-1)/pm)这m个数   中,是否存在一个数mod x为1,若存在,a不是x的原根,否则就是x的原根。 

    我们定义A为p-1的不同素因子的个数,我们发现其增长速率极慢,比N!的反函数增长还慢,我们可以证明在N<1e18内,p不会超过25,不妨视为常数

    那么我们的时间复杂度就达到了

      check 原来的复杂度是O(P-1),现在变成O(25*log(P-1))m为x-1质因子的个数。很明显质因子的个数远远小于x-1。 

     证明如下:

      假设存在一个t < phi(x)=x-1使得at ≡ 1 (mod x) 
      那么由裴蜀定理,一定存在一组k,r使得kt=(x-1)r+gcd(t,x-1) 
      而由欧拉定理有,a(x-1) ≡ 1 (mod x) 
      于是1 ≡ a(kt) ≡ a(xr-r+gcd(t,x-1)) ≡ agcd(t,x-1) (mod x) 
      而t < x-1故gcd(t,x-1) < x-1 
      又gcd(t,x-1)|x-1 于是gcd(t,x-1)必整除(x-1)/p1,(x-1)/p2…(x-1)/pm其中至少一个,设其一为(x-1)/pi 
      那么a((x-1)/pi) ≡ (agcd(t,x-1))s ≡ 1s ≡ 1 (mod x) 
      这与假设矛盾

    练习题:(链接点这里

    #include<bits/stdc++.h>
    #define N 100007
    #define LL long long
    int p[N];
    int l[N>>2],pm[N>>4],tog,tot,mo,x;
    using namespace std;
    LL qsm(LL x,LL y) {
        static LL anw;
        for(anw=1;y;y>>=1,x=x*x%mo) if(y&1) anw=anw*x%mo;
        return anw;
    }
    void getp(int x){
        for (int i=2;i<N;i++) {
            if (!p[i]) l[++tog]=i;
            for (int j=1;j<=tog&&i*l[j]<N;j++) {
                p[i*l[j]]=l[j];
                if (i%l[j]==0) break;
            }
        }
        x=x-1;
        for (int i=1;i<=tog&&l[i]*l[i]<x;i++) 
            if (x%l[i]==0) {
                pm[++tot]=l[i];
                while (x%pm[tot]==0) x/=pm[tot];
            }
        if (x!=1) pm[++tot]=x;
    }
    bool check(int x){
        for (int i=1;i<=tot;i++)
         if (qsm(x,(mo-1)/pm[i])==1) return 0;
        return 1;
    }
    int PP(int x){
        for (int i=1;i<=x;i++)
         if (check(i)) return i;
    }
    int main () {
    //    freopen("a.in","r",stdin);
        scanf("%d",&x);
        getp(x); mo=x;
        printf("%d
    ",PP(x));
    }
  • 相关阅读:
    课堂例子验证
    大道至简第三章读后感
    动手动脑例子验证
    各数相加的思路、流程图、源代码及实现截图
    大道至简第二章读后感
    《大道至简》第一章读后感
    个人冲刺08
    个人冲刺07
    构建之法读后感04
    个人冲刺06
  • 原文地址:https://www.cnblogs.com/rrsb/p/8289964.html
Copyright © 2020-2023  润新知