造板子
求最小原根
复杂度 (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;
}
}
}
}