• 【数论】【快速幂】【扩展欧几里得】【BSGS算法】bzoj2242 [SDOI2011]计算器


    说是BSGS……但是跟前面那题的扩展BSGS其实是一样的……因为模数虽然是质数,但是其可能可以整除a!!所以这两者其实是一样的……

    第一二种操作不赘述。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    ll Quick_Pow(ll a,ll p,ll MOD){
        if(!p){
        	return 1;
        }
        ll ans=Quick_Pow(a,p>>1,MOD);
        ans=ans*ans%MOD;
        if((p&1)==1){
        	ans=(a%MOD*ans)%MOD;
    	}
        return ans;
    }
    void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
        if(!b){
    		d=a;
    		x=1;
    		y=0;
    	}
    	else{
    		exgcd(b,a%b,d,y,x);
    		y-=x*(a/b);
    	}
    }
    #define MAXN 100001
    #define MOD 100003
    struct HashTable
    {
    	ll v[MAXN];
    	int __next[MAXN],first[MOD],en,a[MAXN];
    	void Insert(ll x,int J){
    		if(Find(x)!=-1){
    			return;
    		}
    		int o=x%MOD;
    		v[en]=x;
    		a[en]=J;
    		__next[en]=first[o];
    		first[o]=en++;
    	}
    	int Find(ll x){
    		int o=x%MOD;
    		for(int i=first[o];i!=-1;i=__next[i]){
    			if(v[i]==x){
    				return a[i];
    			}
    		}
    		return -1;
    	}
    	void Clear(){
    		memset(first,-1,sizeof(first));
    		en=0;
    	}
    }T;
    ll a,b,p;
    int zu,op;
    int main(){
    //	freopen("d.in","r",stdin);
    	scanf("%d%d",&zu,&op);
    	for(;zu;--zu){
    		scanf("%lld%lld%lld",&a,&b,&p);
    		if(op==3){
    			T.Clear();
    			b%=p;
    			ll tmp,D=1;
            	int cnt=0;
      			bool flag=0;
        		while((tmp=__gcd(a,p))!=1){
            		if(b%tmp){
    					puts("Orz, I cannot find x!");
    					flag=1;
    					break;
    				}
    				++cnt;
    				p/=tmp;
    				b/=tmp;
    				D=D*a/tmp%p;
    			}
    			if(flag){
    				continue;
    			}
    			int m=ceil(sqrt(p));
    			ll aj=1;
    			T.Insert(aj,0);
    			for(int j=1;j<=m;++j){
    				aj=(a%p*aj)%p;
    				T.Insert(aj,j);
    			}
    			for(int i=0;i<=m;++i){
    				ll x,y,d;
    				exgcd(D,p,d,x,y);
    				x=x*(b/d);
    				x=(x%(p/d)+p/d)%(p/d);
    				int J;
    				if((J=T.Find(x))!=-1){
    					printf("%lld
    ",(ll)i*(ll)m+(ll)J);
    					flag=1;
    					break;
    				}
    				D=(D*aj)%p;
    			}
    			if(!flag){
    				puts("Orz, I cannot find x!");
    			}
    		}
    		else if(op==1){
    			printf("%lld
    ",Quick_Pow(a,b,p));
    		}
    		else{
    			ll d,x,y;
    			exgcd(a,p,d,x,y);
    			if(b%d){
    				puts("Orz, I cannot find x!");
    				continue;
    			}
    			x=x*(b/d);
    			x=(x%(p/d)+p/d)%(p/d);
    			printf("%lld
    ",x);
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    SQL Sever 各版本下载
    使用REPLACE更新某表中某个字段详细内容【SQL语句】
    常用css简写
    CSS hack:区分IE6,IE7,IE8,firefox
    浅析vue中的provide / inject 有什么用处
    Git常用命令总结
    ts
    学会使用Vue JSX,一车老干妈都是你的
    关于javascript的Object. hasOwnProperty,看我就够了
    JavaScript进阶笔记(七):异步任务和事件循环
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6604629.html
Copyright © 2020-2023  润新知