原根

原根的定义是:

$设d_0是满足a^{d_0}equiv 1(\%n)的最小的正整数,如果d_0=varphi (n),那么a是n的原根$

如:

$3$的原根有$2$

$7$的原根有$3,5$

$9$的原根有$2,5$

但是也有可能没有原根,如$10$

但是质数一定有原根,这很重要。

假设$g$是质数$P$的原根,那么有一个很重要的性质:

$g^0,g^1,...,g^{P-2}$和1,2,...,P-1$是一一对应的。

当然,原根不会这么直接考,一般会与FFT,离散对数和N次剩余一起。

好了,就这么多。

原根一般很小,我们直接枚举即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b)  for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

LL ask_euler(LL n)
  {
      LL i,tmp=n,res=1;
      re(i,2,tmp/i)
        if(tmp%i==0)
          {
              res*=(i-1);
              tmp/=i;
              while(tmp%i==0)res*=i,tmp/=i;
          }
      if(tmp!=1)res*=(tmp-1);
      return res;
  }

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

LL power(LL a,LL k,LL Mod){LL x=1;while(k){if(k&1)x=x*a%Mod;a=a*a%Mod;k>>=1;}return x;}

vector<LL>a;
int g_test(LL g,LL eu,LL n)
  {
      int i;
      if(gcd(g,n)!=1)return 0;
      re(i,0,int(a.size())-1)if(power(g,eu/a[i],n)==1)return 0;
      return 1;
  }

LL primitive_root(LL n)
  {
      LL i,eu=ask_euler(n),tmp=eu;//如果已知n为质数,那么eu直接等于n-1 
      a.clear();
      re(i,2,tmp/i)
        if(tmp%i==0)
          {
              a.p_b(i);
              while(tmp%i==0)tmp/=i;
          }
      if(tmp!=1)a.p_b(tmp);
      LL g=1;
      while(!g_test(g,eu,n))g++;
      return g;
  }
View Code
原文地址:https://www.cnblogs.com/maijing/p/4811430.html