P6091原根

题意:求\(n(<=1e6)\)的所有原根

原根定义(图片来自百度百科)

什么样的数有原根?

\(2,4,p^k,2*p^k,p\)奇素数,k正整数

怎么求?

找到最小原根g,其余原根为\(g^k\)

若n存在原根,个数为\(\phi(\phi(n))\),满足\(gcd(k,\phi(n))=1\)

如何找最小原根?

从小到大枚举,最小原根是\(O(n^{\frac 1 4})\)

如何检测?

\(g^{\phi(n)}\equiv1,g^k\not\equiv1(k<\phi(n))\)

关于阶的一条性质:若\(gcd(a,n)=1\),且\(a^k\equiv1\pmod n\),则\(k|\phi(n)\),只需检测\(\phi(n)\)的真因子即可

时间复杂度\(O(n^{\frac14}logn+\phi(n)log\phi(n))\)

步骤:

  1. 线性筛预处理所有质数和有原根的数

  2. \(\phi(n)\)分解因数

  3. 枚举求出最小原根

  4. 通过最小原根求出所有原根

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
#define ll long long
const int N=1e6+4;
inline int ksm(int x,int r,int mod){
	int ret=1;
	for(int i=0;(1<<i)<=r;i++){
		if((r>>i)&1)ret=(ll)ret*x%mod;
		x=(ll)x*x%mod;
	}
	return ret;
}
int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
int n,d,cnt,tot,g,fl;
int pri[N],don[N],b[N],phi[N],ans[N],yin[N];
inline void init(){
	for(int i=2;i<N;i++){
		if(!b[i]){
			pri[++tot]=i;
			phi[i]=i-1;
			if(i&1)don[i]=1;
		}
		for(int j=1;j<=tot&&pri[j]*i<N;j++){
			b[pri[j]*i]=1;
			if(i%pri[j]==0){
				phi[i*pri[j]]=phi[i]*pri[j];
				if(don[i])don[pri[j]*i]=1;
				break;
			}
			else phi[i*pri[j]]=phi[i]*(pri[j]-1);
		}
	}
	for(int i=(N-1)/2;i;i--)
		if(don[i])don[i<<1]=1;
	don[2]=don[4]=1;
}
int main(){
	init();
	int T=read();
	while(T--){
		n=read();d=read();
		if(!don[n]){puts("0\n");continue;}
		ans[0]=cnt=g=0;
		for(int i=1;i<=tot&&pri[i]*pri[i]<=phi[n];i++)
			if(phi[n]%pri[i]==0)yin[++cnt]=phi[n]/pri[i];
		if(phi[n]>1)yin[++cnt]=1; 
		while(++g){
			if(ksm(g,phi[n],n)!=1)continue;
			fl=1;
			for(int i=1;i<=cnt;i++)
				if(ksm(g,yin[i],n)==1){fl=0;break;}
			if(fl)break;
		}
		ans[1]=g;
		for(int i=1;i<=phi[n];i++){
			if(gcd(i,phi[n])!=1)continue;
			ans[++ans[0]]=ksm(g,i,n);
		}
		sort(ans+1,ans+ans[0]+1);
		cout<<ans[0]<<"\n";
		for(int i=d;i<=ans[0];i+=d)cout<<ans[i]<<" ";
		puts("");
	}
	return (0-0);
}
posted @ 2020-04-03 15:09  starusc  阅读(229)  评论(0)    收藏  举报