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;
    }
    

      

  • 相关阅读:
    linq 喜悦
    五班二组高级软件测试作业一总结
    五班二组高级软件测试进度报告
    五班二组黑盒测试实践作业进度报告(1)
    五班二组高级软件测试进度报告
    五班二组高级软件测试进度报告
    [ 语文 ] 西游记50~52回阅读笔记
    [ 具体数学 ] 0:前言
    [ 具体数学 ] 3:和式与封闭式
    [ 历史 ] 黄巢起义
  • 原文地址:https://www.cnblogs.com/bootstar/p/3084400.html
Copyright © 2011-2022 走看看