• 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 otequiv1(k<phi(n)))

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

    时间复杂度(O(n^{frac14}logn+phi(n)logphi(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
    ");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]<<"
    ";
    		for(int i=d;i<=ans[0];i+=d)cout<<ans[i]<<" ";
    		puts("");
    	}
    	return (0-0);
    }
    
  • 相关阅读:
    技术实践 | 聊聊网易云信的信令网络库实践
    打破传统降噪技术 看网易云信在语音降噪的实践应用
    聊聊前端日志库在 SaaS 产品中的应用与设计
    WebRTC 系列之音频会话管理
    简单五步,轻松构建本土「Clubhouse」
    网易云信服务监控平台实践
    基于 Elasticsearch 的数据报表方案
    基于 WebRTC 实现自定义编码分辨率发送
    Python 设计模式—原型模式
    网络层—简单的面试问题
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12626623.html
Copyright © 2020-2023  润新知