zoukankan      html  css  js  c++  java
  • SPOJ Primitive Root

    SPOJ Primitive Root

    给定一个素数P,给定n个数,判断这个n个数是不是P的原根。由原根的定义知: a^x = 1(mod P), x = phi[P],其中x是最小正解。所以也就是求解方程a^x = 1(mod P)的最小正解x满足方程。那么很直接的办法就是用Baby-Step-Giant-Step求解,但是复杂度很高。由欧拉定理知道:a^(Phi[P]) = 1(mod P),那么如果a不是P的原根,也就是说x<Phi[p],很容易证明Phi[p]%x==0。那么我们可以这么做,枚举Phi[p]的每一个约数i(i != Phi[p]), 判断(a^i)%P==1是否成立。如果成立,那么说明a不是P的原根。这样复杂度就降低为O(log(T)),其中T是P的所有约数的乘积,T不会超过2^100。

    #include <stdio.h>
    #include <string.h>
    typedef long long LL;
    const int maxn = 50000;
    int prim[maxn+10], f[100], amount[100], cnt;
    
    void init(){
        for(int i = 2; i <= maxn; i ++){
            if(!prim[i]) prim[cnt ++] = i;
            for(int j = i+i; j <= maxn; j += i){
                prim[j] = 1;
            }
        }
    }
    int calcFactor(LL n){
        int l = 0;
        for(int i = 0; i < cnt; i ++){
            if(n%prim[i]==0){
                f[l] = prim[i];
                int t = 0;
                while(n%prim[i]==0) n = n/prim[i], t ++;
                amount[l ++] = t;
            }
        }
        if(n!=1) f[l] = n, amount[l++] = 1;
        return l;
    }
    
    LL pow_mod(LL a, LL n, LL mod){
        LL ret = 1;
        while(n){
            if(n&1) ret = ret * a%mod;
            a = a * a%mod;
            n>>=1;
        }
        return ret;
    }
    bool dfs(LL a, LL phi, LL mod, LL v, int l, int cur){
        if(cur==l) return false;
        LL k = 1;
        for(int i = 0; i <= amount[cur]; i ++){
            if(i) k = k * f[cur];
            if(v*k!=1 && v*k!=phi && (pow_mod(a, v*k, mod) ==1 || pow_mod(a, phi/v/k, mod)==1))
                return true;
            bool ok = dfs(a, phi, mod, v*k, l, cur+1);
            if(ok) return true;
        }
        return false;
    }
    
    int main(){
        LL p, a;
        int n;
        init();
        while(scanf("%lld%d", &p, &n), n&&p){
            LL phi = p-1;
            int l = calcFactor(phi);
            while(n--){
                scanf("%lld", &a);
                bool ok = dfs(a, phi, p, 1, l, 0);
                puts(ok ? "NO" : "YES");
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    疫情在家没事做推荐个学习的目录:怎么从一名码农成为架构师的必看知识点:目录大全(不定期更新)
    教你使用 Swoole-Tracker 秒级定位 PHP 卡死问题
    怎样深入学习php,成为php高手!?
    PHP实现简单RPC
    PHP工作岗位要求
    关于PHP在企业级开发领域的访谈
    未知及待办清单
    siege报告学习
    session&token based auth登录方式描述
    学习JWT
  • 原文地址:https://www.cnblogs.com/bootstar/p/3084400.html
Copyright © 2011-2022 走看看