[大佬blog](https://www.cnblogs.com/cjoieryl/p/8438756.html)
令Ord(a,b)= 最小的使 a ^ n % b == 1 的n
那么若a是b的原根,则Ord(a,b)=phi(b)
最小原根一般ha以枚举
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#define maxn 1000005
using namespace std;
int n;
int pr[maxn],cnt_pr;
bool vis[maxn];
void Euler_sieve(int lim)
{
for(int i=2,j;i<=lim;i++)
{
if(!vis[i]){ pr[cnt_pr++]=i; }
for(j=0;j<cnt_pr && pr[j]*i<=lim;j++)
{
vis[pr[j]*i]=1;
if(i%pr[j]==0) break;
}
}
}
int pow(int base,int deg,int p)
{
int ret=1;
for(;deg;deg>>=1,base=1ll*base*base%p) if(deg&1) ret=1ll*ret*base%p;
return ret;
}
int fac[maxn];
bool check(int num)
{
for(int i=1;i<=fac[0];i++)
if(pow(num,(n-1)/fac[i],n)==1)
return 0;
return 1;
}
int main()
{
scanf("%d",&n);
Euler_sieve((int)(sqrt(n)+1));
for(int i=0,sum=n-1;i<cnt_pr && pr[i]*pr[i]<=sum;i++)
if(sum%pr[i]==0)
{
fac[++fac[0]]=pr[i];
while(sum%pr[i]==0)
sum/=pr[i];
}
for(int i=2;i<n;i++)
if(check(i))
{
printf("%d\n",i);
break;
}
}
原根还可以用于NTT,性质类似单位根。
NTT模板:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define maxn 4000005
using namespace std;
int n,m,len;
int P=998244353,G=3,invG;
int wn[2][30];
int pow(int base,int deg,int P)
{
int ret=1;
for(;deg;deg>>=1,base=1ll*base*base%P) if(deg&1) ret=1ll*ret*base%P;
return ret;
}
void Prework()
{
invG=pow(G,P-2,P);
for(int i=1;i<=20;i++) wn[1][i]=pow(G,(P-1)/(1<<i),P),wn[0][i]=pow(invG,(P-1)/(1<<i),P);
}
int A[maxn],B[maxn];
void NTT(int *A,int n,int typ)
{
for(int i=0,j=0,k;i<n;i++)
{
if(i<j) swap(A[i],A[j]);
for(k=n>>1;k;k>>=1) if((j^=k)>=k) break;
}
for(int i=1,j,k,len,w,x,y;(1<<i)<=n;i++)
{
len=1<<(i-1);
for(j=0;j<n;j+=1<<i)
{
w=1;
for(k=0;k<len;k++,w=1ll*w*wn[typ][i]%P)
{
x=A[j+k],y=1ll*A[j+k+len]*w%P;
A[j+k]=(x+y)%P;
A[j+k+len]=(x-y)%P;
}
}
}
if(typ==0)
for(int i=0,inv=pow(n,P-2,P);i<n;i++)
A[i]=1ll*A[i]*inv%P;
}
int main()
{
Prework();
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) scanf("%d",&A[i]);
for(int i=0;i<=m;i++) scanf("%d",&B[i]);
for(len=1;len<=(n+m);len<<=1);
NTT(A,len,1);
NTT(B,len,1);
for(int i=0;i<=len;i++) A[i]=1ll*A[i]*B[i]%P;
NTT(A,len,0);
for(int i=0;i<n+m;i++) printf("%d ",(A[i]+P)%P);
printf("%d\n",(A[n+m]+P)%P);
}