zoukankan      html  css  js  c++  java
  • BZOJ.2242.[SDOI2011]计算器(扩展欧几里得 BSGS)

    同余方程都不会写了。。还一直爆int

    /*
    2.关于同余方程ax ≡b(mod p),可以用Exgcd做,但注意到p为质数,y一定有逆元 
    首先a%p=0时 仅当b=0时有解;然后有x ≡b*a^-1(mod p),a,p互质,可用快速幂求a的逆元,*b的得到x 
    但是扩欧还是比快速幂快的 
    */
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    typedef long long LL;
    const int MAXIN=1<<17,N=1e5,mod=5e6;
    char IN[MAXIN],*SS=IN,*TT=IN;
    struct HASH
    {
    	int Enum,H[mod+3],nxt[N],to[N],val[N];
    	void Init() {memset(H,0,sizeof H), Enum=0;}
    	inline void AddEdge(int u,int v)
    	{
    		int x=u%mod;
    		for(int i=H[x];i;i=nxt[i])
    			if(val[i]==u) {to[i]=v; return;}
    		to[++Enum]=v, val[Enum]=u, nxt[Enum]=H[x], H[x]=Enum;
    	}
    	int Query(int u)
    	{
    		int x=u%mod;
    		for(int i=H[x];i;i=nxt[i])
    			if(val[i]==u) return to[i];
    		return -1;
    	}
    }hs;
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    int Fast_Pow(LL a,int k,int p)
    {
    	LL t=1;
    	for(;k;k>>=1,a=a*a%p)
    		if(k&1) t=t*a%p;
    	return t;
    }
    int gcd(int a,int b)
    {
    	return b?gcd(b,a%b):a;
    }
    void Exgcd(int a,int b,int &x,int &y)
    {
    	if(!b) {x=1,y=0; return;}
    	Exgcd(b,a%b,x,y);
    	int t=x; x=y,y=t-a/b*y;
    }
    void Solve2(int a,int b,int p)//calc ax=b(mod p)->ax-py=b
    {
    	int g=gcd(a,p);
    	if(b%g) {puts("Orz, I cannot find x!"); return;}
    	int x,y;
    	Exgcd(a,p,x,y);//calc ax+by=gcd(a,b) or a/=g,b/=g,ax+by=1
    	x=1LL*x*(b/g)%p;//ax*c/gcd+by*c/gcd=c*gcd/gcd=c
    	p/=g;
    	printf("%d
    ",(x%p+p)%p);//x=x_0+k*p/g
    }
    void BSGS(int a,int b,int p)//a^x ≡b(mod p)
    {
    	if(gcd(a,p)!=1) {puts("Orz, I cannot find x!"); return;}
    	hs.Init();
    	int m=ceil(sqrt(p-1));
    	LL t=b%p,AM;
    	for(int j=0;j<=m;++j) hs.AddEdge(t,j),t=t*a%p;
    	AM=Fast_Pow(a,m,p),t=AM;
    	for(int v,i=1;i<=m;++i,t=t*AM%p)
    		if((v=hs.Query(t))!=-1) {printf("%d
    ",(1LL*i*m-v)%p); return;}
    	puts("Orz, I cannot find x!");
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("2242.in","r",stdin);
    #endif
    
    	int t=read(),k=read(),a,b,p,x,y;
    	while(t--)
    	{
    		a=read(),b=read(),p=read();
    		if(k==1) printf("%d
    ",Fast_Pow(a,b,p));
    		else if(k==2) Solve2(a,b,p);
    		else BSGS(a,b,p);
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何评测软件工程知识技能水平?
    创新产品的需求分析:未来的图书会是什么样子?
    案例分析:设计模式与代码的结构特性
    业务领域建模Domain Modeling
    转载:10 Easy Steps to a Complete Understanding of SQL
    二十六个月Android学习工作总结
    android sdk无法更新问题解决
    android中利用view画出一条竖线
    android-Java SoftReference,WeakReference,Direct Reference简介
    Intellij IDEA开发第一个android应用教程
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8325246.html
Copyright © 2011-2022 走看看