• #费马小定理,BSGS#BZOJ 3285 离散对数解指数方程


    题目

    求最小的正整数 (x) 满足 (g^{ax+b}equiv cpmod p)
    其中 (p) 是一个质数, (g,a,b,cleq 10^{1000000},pleq 2^{31})


    分析

    先将 (g^a)(g^b) 用费马小定理求出来,

    问题就转换成 (b' imes {a'}^xequiv c'pmod p)

    这个直接套用 BSGS 就可以了


    代码

    #include <cstdio>
    #include <cctype>
    #include <cmath>
    #include <cstring>
    #define rr register
    using namespace std;
    const int p=70001; typedef long long lll;
    const int N=1000011; char A[N],B[N],C[N],G[N];
    lll mod,lA,lB,lC,ans,lG,a,b,c,g;
    struct Linked_Hash{
    	struct node{int y,w,next;}E[p]; int Et,hs[p];
    	inline void Clear(){Et=0,memset(hs,-1,sizeof(hs));}
    	inline void Insert(int w,int x){E[++Et]=(node){x,w,hs[w%p]},hs[w%p]=Et;}
    	inline signed locate(int W){
    		for (rr int i=hs[W%p];~i;i=E[i].next)
    		    if (E[i].w==W) return E[i].y;
    		return -1;
    	}
    }ha;
    inline lll gcd(lll x,lll y){return y?gcd(y,x%y):x;}
    inline lll exBSGS(lll a,lll c,lll b,lll mod){
    	ha.Clear();
    	rr lll GCD=gcd(a,mod),t=1;
    	rr lll CNT=0,ir=sqrt(mod)+1;
    	while (GCD>1){
    		if (b%GCD||c%GCD) return -1;
    		b/=GCD,c/=GCD,mod/=GCD,
    		t=t*(a/GCD)%mod,
    		GCD=gcd(a,mod),++CNT;
    		if (b==t*c%mod) return CNT;
    	}
    	rr lll now=1;
    	for (rr int i=0;i<ir;++i)
    	    ha.Insert(now*b%mod,i),now=now*a%mod;
    	a=now,now=t;
    	if (!a) return !b?1:-1;
    	for (rr int i=0;i<=ir;++i){
    		rr int j=ha.locate(now*c%mod);
    		if (j>=0&&i*ir+CNT>j) return i*ir+CNT-j;
    		now=now*a%mod;
    	}
    	return -1;
    }
    inline lll ksm(lll x,lll y){
    	rr lll ans=1;
    	for (;y;y>>=1,x=x*x%mod)
    	    if (y&1) ans=ans*x%mod;
    	return ans; 
    }
    signed main(){
    	scanf("%s%s%s%s%lld",A+1,B+1,C+1,G+1,&mod);
    	lA=strlen(A+1),lB=strlen(B+1),lC=strlen(C+1),lG=strlen(G+1);
    	for (rr int i=1;i<=lG;++i) g=(g*10+G[i]-48)%mod;
    	for (rr int i=1;i<=lC;++i) c=(c*10+C[i]-48)%mod;
    	for (rr int i=1;i<=lA;++i) a=(a*10+A[i]-48)%(mod-1);
    	for (rr int i=1;i<=lB;++i) b=(b*10+B[i]-48)%(mod-1);
    	a=ksm(g,a),b=ksm(g,b),ans=exBSGS(a,b,c,mod);
    	if (ans==-1) printf("no solution");
    	    else printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    oldboy_09_03day_test1
    oldboy_09_03day
    java消息队列
    es6语法([...arr], set/map数据结构,数组扩展,箭头函数等)
    Angular 2 Expression Changed After It Has Been Checked Exception
    jQuery之Deferred对象详解
    js面向对象:Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
    Angular 4.x 动态创建组件
    JS中this的四种用法
    typescript主键自增长
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15333313.html
Copyright © 2020-2023  润新知