zoukankan      html  css  js  c++  java
  • POJ2417 Discrete Logging

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

     

    本文作者:ljh2000

     

    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

     

    Description

    Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that 
        B
    L
     == N (mod P)

    Input

    Read several lines of input, each containing P,B,N separated by a space.

    Output

    For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".

    Sample Input

    5 2 1
    5 2 2
    5 2 3
    5 2 4
    5 3 1
    5 3 2
    5 3 3
    5 3 4
    5 4 1
    5 4 2
    5 4 3
    5 4 4
    12345701 2 1111111
    1111111121 65537 1111111111
    

    Sample Output

    0
    1
    3
    2
    0
    3
    1
    2
    0
    no solution
    no solution
    1
    9584351
    462803587
    

    Hint

    The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states 
       B
    (P-1)
     == 1 (mod P)

    for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m 
       B
    (-m)
     == B
    (P-1-m)
     (mod P) .

    Source

    正解:BSGS算法

    解题报告:

      BSGS模板题。

      BSGS又称大步小步算法(有人戏称之为拔山盖世算法),其实应该算是一种优化暴力,是一种用空间换时间的办法。

      首先我们想对于$a^{x} equiv b$ ($mod p$),$a、b、p$已知,求最小的正整数$x$。不妨设  $m= sqrt{p}  $  取上整,令 $x=i*m+j$ ,那么我把原式化开之后就可以得到$a^{m*i}与b*a^{j}$关于p同余。对于右边值从$0$到$m$枚举$j$,把值插入哈希表,对于左边值从$1$到$m$枚举$i$,把值在哈希表中查询看是否存在,查询到的第一个答案即为所求。如果找不到的话,考虑因为我等于是枚举了$ a^{p} $以内的所有情况,但是还没有找到,根据费马小定理,指数大于$p$一定无解。

      正确性的话应该是很好想通的,因为i枚举一开始就是$1$,乘上$m$之后显然一定比$b$大。

      另外注意一点,因为插入哈希表时如果出现了相等的情况,显然$j$越大越好,所以j从小到大枚举时可以直接覆盖掉之前的结果。

    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    using namespace std;
    typedef long long LL;
    const int MOD = 300007;
    const int MAXM = 100000;
    LL p,b,ans,n,to[MAXM],next[MAXM];
    int ecnt,first[MOD+12],block,w[MAXM];
    inline LL gcd(LL x,LL y){ if(y==0) return x; return gcd(y,x%y);  }
    inline LL fast_pow(LL x,LL y){ if(y==0) return 1; LL r=1; while(y>0) { if(y&1) r*=x,r%=p; x*=x; x%=p; y>>=1; } return r; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void insert(LL x,int j){
    	LL cc=x; x%=MOD; for(int i=first[x];i;i=next[i]) if(to[i]==cc) { w[i]=j; return ; }
    	next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=cc; w[ecnt]=j;
    }
    
    inline LL query(LL x){
    	LL cc=x; x%=MOD; for(int i=first[x];i;i=next[i]) if(to[i]==cc) return w[i];
    	return -1;
    }
    
    inline void work(){
    	bool ok;
    	while(scanf("%lld",&p)!=EOF) {
    		b=getint(); n=getint();	ans=0;	if(n==1) { printf("0
    "); continue; }
    		if(gcd(b,p)!=1) { printf("no solution
    "); continue; }
    		memset(first,0,sizeof(first)); ecnt=0;
    		block=sqrt(p); if(block*block<p) block++;
    		for(int i=0;i<=block;i++) insert((n*fast_pow(b,i))%p,i);
    		LL bm=fast_pow(b,block); ok=false;
    		for(int i=1;i<=block;i++) {
    			ans=query(fast_pow(bm,i)); 
    			if(ans==-1) continue;
    			ok=true; printf("%lld
    ",(LL)i*block-ans);
    			break;
    		}
    		if(!ok)	printf("no solution
    ");
    	}
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

  • 相关阅读:
    【iOS】Objective-C 字符串操作
    【生活】“外卖”中的猫腻
    【Nodejs】Expressのサンプルについて
    【Nodejs】ExpressのRequestとResponseの内容
    【Nodejs】Node.js(Express)の環境構築
    JS 判断数组包含某个字符
    新路由器只能聊QQ,不能上其它的网
    JS form 表单收集 数据 formSerialize
    JS 经验总结
    数据库收缩日志文件
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6230999.html
Copyright © 2011-2022 走看看