zoukankan      html  css  js  c++  java
  • BZOJ1319 Sgu261Discrete Roots

    本题在数论上面的考察不亚于SDOI2017树点涂色一题在树论上的考察

    Description

    link

    求满足 (x^kequiv a (mod p)) 的所有的 (x)

    (xin[0,p-1])

    保证 (p) 为质数

    Solution

    先把 (a=0) 的判掉

    我们发现一般的 (bsgs) 可以求指数,但是不能求底数

    那么我们转化一发:

    原根科技!!!

    原根相关的一篇让我大概懂了的博客

    求原根啥的 (51nod) 上面有题做

    我们发现 (p) 是个素数,就会有原根


    原根的求法

    如果是个质数,那么就找到 (p-1) 所有的质因子,

    然后上判断当前的值 (x) 是不是可以满足对于所有的 (d_i) 不存在 (x^{frac {p-1} {d_i}} equiv 1 (mod p))


    求完原根之后,我们就可以把右边表示成

    [g^{id_a} ]

    左边也就成了:

    [(g^{id_x})^k ]

    所以推推式子:

    这个(id_x imes kequiv id_a (mod varphi(p)))

    理解:指数上有欧拉定理……

    (id_a) 是可以 (bsgs) 求的,(k) 是个给的

    然后就上 (exgcd)(id_x) 的解和通解求一求

    最后输出就 (OK)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	inline int ksm(int x,int y,int p)
    	{
    		int res=1; for(;y;y>>=1,(x*=x)%=p) if(y&1) (res*=x)%=p; 
    		return res;
    	}
    	inline void exgcd(int a,int b,int &x,int &y)
    	{
    		if(!b) return x=1,y=0,void();
    		exgcd(b,a%b,x,y); int t=x; x=y; 
    		y=t-(a/b)*y;
    		return ;
    	}
    	const int N=2e5+10;
    	int d[N],cnt,p,k,a;
    	inline bool check(int x)
    	{
    		for(int i=1;i<=cnt;++i) if(ksm(x,(p-1)/d[i],p)==1) return 0;
    		return 1;
    	}
    	inline int find(int p)
    	{
    		int t=p-1; 
    		for(int i=2;i*i<=t;++i) 
    		{
    			if(t%i!=0) continue;
    			d[++cnt]=i; while(t%i==0) t/=i;
    		} if(t!=1) d[++cnt]=t;
    		int g=1; while(g<p) if(check(g)) return g; else g++;
    		return -1;
    	}
    	map<int,int> mp;
    	inline int bsgs(int y,int z,int p)
    	{
    		int s=ceil(sqrt(p)),t=z%p; mp[t]=0;
    		for(int i=1;i<=s;++i) (t*=y)%=p,mp[t]=i;
    		int base=ksm(y,s,p),now=1;
    		for(int i=1;i<=s;++i) 
    		{
    			(now*=base)%=p; 
    			if(!mp.count(now)) continue;
    			int t=i*s-mp[now]; 
    			return (t%p+p)%p;
    		}
    	}
    	int num,out[N];
    	signed main()
    	{
    		p=read(); k=read(); a=read();
    		if(!a) return puts("1
    0"),0; 
    		int g=find(p),ans=bsgs(g,a,p);
    		int gcd=__gcd(k,p-1);
    		if(ans%gcd) return puts("0"),0;
    		int A=k/gcd,B=(p-1)/gcd,x,y;
    		exgcd(A,B,x,y);
    		(x+=B)%=B; x=(x*(ans/gcd)+B)%B;
    		while(x<p-1)
    		{
    			out[++num]=ksm(g,x,p);
    			x+=B;
    		} sort(out+1,out+num+1);
    		printf("%lld
    ",num);
    		for(int i=1;i<=num;++i) printf("%lld
    ",out[i]);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    Review

    如果出现了底数不好求的情况

    我们用原根把底数的计算转到质数上再进行其他操作

  • 相关阅读:
    Restful API 指南
    git submodule 使用小结
    git 在 A 项目中引用 B 项目
    Error Permission denied when running brew cleanup
    @Scope注解设置创建bean的方式和生命周期
    spring常用注解
    Spring的AOP配置文件和注解实例解析
    java线程的状态
    java线程执行的优先级
    java创建线程的方法
  • 原文地址:https://www.cnblogs.com/yspm/p/12901853.html
Copyright © 2011-2022 走看看