原根学习篇

 

原根学习篇
Caption

HDU2619

求原根的数量

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll euler(ll n){
	ll ans = n;
	for(int i=2;i*i<=n;i++){
		if(n % i == 0){
			ans = ans / i * (i - 1);
			while(n % i == 0)	n /= i;
		}
	}
	if(n > 1)	ans = ans / n * (n - 1);
	return ans;
}
int main(){
	while(~scanf("%d",&n)){
		printf("%lld\n",euler(n-1));
	}
	return 0;
}

51nod1135

求最小原根

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p;
vector<ll>v;
void factor(ll p){
	for(ll i=2;i*i<=p;i++){
		if(p % i == 0){
			v.push_back(i);
			while(p % i == 0)	p /= i;
		}
	}
	if(p > 1)	v.push_back(p);
	sort(v.begin(),v.end());
}
ll power(ll a,ll n,ll mod){
	ll ans = 1;
	while(n){
		if(n&1)	ans = ans * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return ans;
}
ll solve(ll p){
	for(ll g=2;g<=p-1;g++){    //枚举原根
		bool flag = true;
		for(int i=0;i<v.size();i++)
			if(power(g,(p-1)/v[i],p) == 1){
				flag = false;
				break;
			}
		if(flag)	return g;
	}
}
int main(){
	scanf("%lld",&p);	
	factor(p-1);
	printf("%lld\n",solve(p));
	return 0;
}