P6091 【模板】原根

给定整数 n,求它的所有原根。

为了减小你的输出量,给出输出参数 dd,设 nn 的所有原根有 cc 个,从小到大分别为 g_1,\ldots,g_cg1,,gc,你只需要依次输出

 

P6091 【模板】原根_第1张图片

 

 

int phi[maxn];
int prime[maxn];   
int vis[maxn];     
int rt[maxn];
ll fac[maxn];
ll ans[maxn];
int cnt,num;

int euler_sieve(int n) {
    int cnt = 0;
    for (int i = 2; i <= n; i++) {
        if (!vis[i]) prime[cnt++] = i;
        for (int j = 0; j < cnt; j++) {
            if (i * prime[j] > n) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    return cnt;  
}

void phi_table(int n) {
    for (int i = 2; i <= n; i++) phi[i] = 0;
    phi[1] = 1;
    for (int i = 2; i <= n; i++) if (!phi[i])
        for (int j = i; j <= n; j += i) {
            if (!phi[j]) phi[j] = j;
            phi[j] = phi[j] / i * (i - 1);
        }
}

void init(int tot) {
    rt[2] = rt[4] = 1;
    for (int i = 1; i < tot; i++) {
        for (int j = 1; (1ll * j * prime[i]) <= maxn - 10; j *= prime[i]) rt[j * prime[i]] = 1;
        for (int j = 2; (1ll * j * prime[i]) <= maxn - 10; j *= prime[i]) rt[j * prime[i]] = 1;
    }
 }

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

ll quickPower(ll a, ll b, ll m) {
    ll res = 1;
    ll base = a;
    while (b) {
        if (b & 1) {
            res *= base;
            res %= m;
        }
        base *= base;
        base %= m;
        b >>= 1;
    }
    return res;
}


void get_fac(int p) {
    for (int i = 2; i * i <= p; i++) {
        if (p % i == 0) {
            fac[++cnt] = i;
            while (p % i == 0) p /= i;
        }
    }
    if (p > 1) fac[++cnt] = p;
}

bool check ( ll x, ll p ) {
    if (quickPower(x, phi[p], p) != 1) return 0;
    for (int i = 1; i <= cnt; i++) {
        if (quickPower(x, phi[p] / fac[i], p) == 1) return 0;
    }
    return 1;
}

int find_rt(ll p) {
    for (int i = 1; i < p; i++) if (check(i, p)) return i;
    return 0;
}

void get_rt(ll p, ll x) {
    int prod = 1;
    for (int i = 1; i <= phi[p]; i++) {
        prod = (1ll * prod * x) % p;
        if (gcd(i, phi[p]) == 1) ans[++num] = prod;
    }
}

int main() {
    int tot = euler_sieve(maxn);
    phi_table(maxn);
    init(tot);
    int T;
    ll n, d;
    scanf("%d", &T);
    while (T--) {
        scanf("%lld%lld", &n, &d);
        if (rt[n]) {
            cnt = num = 0;
            get_fac(phi[n]);
            ll mm = find_rt(n);
            get_rt(n, mm);
            sort(ans + 1, ans + num + 1);
            printf("%d\n", num);
            for (int i = 1; i <= num / d; i++) printf("%d ", ans[i * d]);
            puts("");
        }
        else puts("0\n");
    }
}

 

你可能感兴趣的:(P6091 【模板】原根)