1. 程式人生 > >51nod1135 原根+模板

51nod1135 原根+模板

設m是正整數,a是整數,若a模m的階等於φ(m),則稱a為模m的一個原根。

a^r  1(mod m)  最小的一個r就是a模m的階。

假如m是素數a^(m-1)  1 (mod m) 當且僅當指數為m-1時成立,a就是m的原根。

(a^i)%m兩兩不同(0 <= i < p, 1 < a < p), a就是m的原根。

假如m有原根那麼它一共有φ(φ(m))個原根。

求素數原根的方法:對p-1質因子分解p-1 = p1^a1 * p2^a2 * p3^a3...若恆有a^((p-1)/pi) ≠ 1(mod p)成立那麼a就是p的原根(對於合數求原根,只需要把p-1換成φ(p)即可)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
ll qpow(ll a, ll b, ll m) {ll ans = 1;while(b) {if(b % 2) ans = ans * a % m;a = a * a % m;b >>= 1;}return ans % m;}

ll factor[maxn], k = 0;
void decompose(ll x) {//分解質因子 
	ll ans = 0;
	for (ll i = 2; i * i <= x; i++) {
		if (x % i == 0) {
			factor[k++] = i;
			while (x % i == 0)	x /= i;
		}
	}
	if (x > 1)	factor[k++] = x;
}

ll cal(ll n) {//求素數最小原根 
	decompose(n - 1);
	for (ll g = 2; g < n; g++) {
		int flag = 1;
		for (int i = 0; i < k; i++) {
			ll t = (n - 1) / factor[i];
			if (qpow(g, t, n) == 1) {
				flag = 0;
				break;
			}
		}
		if (flag == 1)
			return g;
	}
}

int main() {
	ll n;
	scanf("%lld", &n);
	ll ans = cal(n);
	printf("%lld\n", ans);
	return 0;
}