原根学习篇
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;
}