zoukankan      html  css  js  c++  java
  • luogu P6091 原根

    LINK:原根

    再复习一下原根 防止考场上要NTT求原根的时候不会求...

    这道题要求求出n之内的所有原根 根据原根的定义。

    原根指 若x对于模n的阶为phi(n)且(1leq xleq n) 那么称x为n的原根.

    暴力做法枚举x 枚举phi(n)的因数 看其是否同余1.

    复杂度nsqrt(n)左右。

    考虑更快的做法 (去年省选骗分过样例也用了这个做法

    考虑求出最小的原根g(暴力,但是很快. 对于剩下的原根都可以表示成g^k,条件为(k,phi(n))==1.(显然。

    于是就做完了。值得一提的是我们还需要知道一个数字是否有原根。

    有原根的必要充要条件:2,4,p^k,2*p^k.其中p为奇质数。

    const int MAXN=1000010;
    int T,top,cnt,n,maxx;
    int p[MAXN],v[MAXN],phi[MAXN],vis[MAXN],s[MAXN],an[MAXN];
    inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
    inline void prepare()
    {
    	phi[1]=1;
    	for(int i=2;i<=maxx;++i)
    	{
    		if(!v[i]){p[++top]=v[i]=i;phi[i]=i-1;}
    		rep(1,top,j)
    		{
    			if(maxx/i<p[j])break;
    			int ww=i*p[j];
    			v[ww]=p[j];
    			if(v[i]==p[j]){phi[ww]=phi[i]*p[j];break;}
    			phi[ww]=phi[i]*(p[j]-1);
    		}
    	}
    	vis[2]=1;vis[4]=1;
    	rep(2,top,i)
    	{
    		for(ll j=1*p[i];j<=maxx;j=j*p[i])vis[j]=1;
    		for(ll j=2*p[i];j<=maxx;j=j*p[i])vis[j]=1;
    	}
    }
    inline int ksm(ll b,int p,int mod)
    {
    	ll cnt=1;
    	while(p)
    	{
    		if(p&1)cnt=cnt*b%mod;
    		b=b*b%mod;p=p>>1;
    	}
    	return cnt;
    }
    inline void fj(int x)
    {
    	top=0;
    	for(int i=1;p[i]*p[i]<=x;++i)
    		if(x%p[i]==0)
    		{
    			s[++top]=p[i];
    			while(x%p[i]==0)x/=p[i];
    		}
    	if(x>1)s[++top]=x;
    }
    inline int check(int x,int p)
    {
    	if(ksm(x,phi[p],p)!=1)return 0;
    	rep(1,top,i)
    		if(ksm(x,phi[p]/s[i],p)==1)return 0;
    	return 1;
    }
    inline int getg(int p)
    {
    	rep(1,p-1,i)if(check(i,p))return i;
    	return 0;
    }
    inline void get_ans(int g,int p)
    {
    	cnt=0;ll ww=1;
    	rep(1,phi[p],i)
    	{
    		ww=ww*g%p;
    		if(gcd(i,phi[p])==1)an[++cnt]=ww;
    	}
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(T);maxx=1000000;prepare();
    	while(T--)
    	{
    		get(n);int d;get(d);
    		if(vis[n])
    		{
    			fj(phi[n]);
    			get_ans(getg(n),n);
    			sort(an+1,an+1+cnt);
    			put(cnt);
    			rep(1,cnt/d,i)printf("%d ",an[i*d]);
    		}
    		else puts("0");
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOS 判断两个日期之间的间隔
    iOS UITextField设置placeholder颜色
    iOS 当键盘覆盖textFiled时简单的处理方法
    iOS 点击空白处收回键盘的几个简单代码
    iOS 字符串和图片互转
    JDBC连接数据库
    Java虚拟机原理和调优
    java读写文件IO
    MultipartFile 获取上传TXT文件字数
    Runtime.getRuntime().exec()实现Java调用python程序
  • 原文地址:https://www.cnblogs.com/chdy/p/12555677.html
Copyright © 2011-2022 走看看