[51nod1135] 原根

造板子

求最小原根

复杂度 \(O(n^{1/4} \log n)\)

// Parameter: N
// Method: init()!!! solve(p)
// Output: min proot (returned)
namespace proot {

const int N = 1000005;

int cnt, tot, p;
int vis[N], pr[N], fac[N];

void GetPrime() {
    cnt = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 2; i < N; i++) {
        if(!vis[i]) {
            pr[cnt++] = i;
            for(int j = 0; j < cnt && pr[j] * i < N; j++) {
                vis[i * pr[j]] = 1;
                if(i % pr[j] == 0) break;
            }
        }
    }
}

void Factor(int x) {
    tot = 0;
    int t = (int) sqrt(x + 0.5);
    for(int i = 0; pr[i] <= t; i++) {
        if(x % pr[i] == 0) {
            fac[tot++] = pr[i];
            while(x % pr[i] == 0) x /= pr[i];
        }
    }
    if(x > 1) fac[tot++] = x;
}

int quick_pow(int n, int m, int mod) {
    int res = 1, tmp = n % mod;
    while(m) {
        if(m & 1) res = res * tmp % mod;
        tmp = tmp * tmp % mod;
        m >>= 1;
    }
    return res;
}

void init() {
    GetPrime();
}

int solve(int _p) {
    p=_p;
    Factor(p - 1);
    for(int g = 2; g < p; g++) {
        bool flag = true;
        for(int i = 0; i < tot; i++) {
            int t = (p - 1) / fac[i];
            if(quick_pow((int)g, (int)t, (int)p) == 1) {
                flag = false;
                break;
            }
        }
        if(flag) {
            return g;
            break;
        }
    }
}
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12348696.html