HDU 2815 扩展baby step giant step 算法

题目大意就是求 a^x = b(mod c) 中的x

用一般的baby step giant step 算法会超时

这里参考的是http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4

map平衡树查找值

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <cmath>
 5 #include <map>
 6 using namespace std;
 7 #define ll long long
 8 
 9 int q_pow(int a , int b , int mod)
10 {
11     ll ans = 1;
12     while(b)
13     {
14         if(b&1) ans =((ll)ans*a)%mod;
15         a = ((ll)a*a)%mod;
16         b>>=1;
17     }
18     return ans;
19 }
20 
21 int gcd(int a , int b)
22 {
23     if(b == 0)return a;
24     else return gcd(b,a%b);
25 }
26 
27 int ex_gcd(int a , int &x , int b , int &y)
28 {
29     if(b == 0){
30         x=1 , y=0;
31         return a;
32     }
33     int ans = ex_gcd(b , x , a%b , y);
34     int t = x;
35     x=y , y = t-a/b*y;
36     return ans;
37 }
38 
39 int inv(int a , int b , int mod)
40 {
41     int x , y , d;
42     d = ex_gcd(a , x , mod , y);
43     int e = (ll)x*b%mod;
44     return e<0?e+mod:e;
45 }
46 
47 int BabyStep(int A,int B,int C){
48     map<int,int> Hash;
49     ll buf=1%C,D=buf,K;
50     int i,d=0,tmp;
51     for(i=0;i<=100;buf=buf*A%C,++i)
52         if(buf==B) return i;
53     while((tmp=gcd(A,C))!=1)
54     {
55         if(B%tmp)return -1;
56         ++d;
57         C/=tmp;
58         B/=tmp;
59         D=D*A/tmp%C;
60     }
61     Hash.clear();
62     int M=(int)ceil(sqrt((double)C));
63     for(buf=1%C,i=0;i<=M;buf=buf*A%C,++i)
64         if(!Hash.count((int)buf))Hash[(int)buf]=i;
65     for(i=0,K=q_pow((ll)A,M,C);i<=M;D=D*K%C,++i)
66     {
67         tmp=inv(D,B,C);
68         if(tmp>=0&&Hash.count(tmp))return i*M+Hash[tmp]+d;
69     }
70     return -1;
71 }
72 int main()
73 {
74    // freopen("a.in" ,"r" , stdin);
75     int k , p , n;
76     while(scanf("%d%d%d" , &k , &p , &n) == 3)
77     {
78         if(n>=p){
79             puts("Orz,I can’t find D!");
80             continue;
81         }
82         int ans = BabyStep(k , n , p);
83         if(ans == -1) puts("Orz,I can’t find D!");
84         else printf("%d\n" , ans);
85     }
86     return 0;
87 }
View Code

 

 hash表查找值(效率高很多)hash是线性查找:

技术分享
  1 #include<iostream>
  2 #include<map>
  3 #include<cmath>
  4 #include <cstdio>
  5 using namespace std;
  6 typedef long long LL;
  7 const int maxn = 65535;
  8 struct hash{
  9     int a,b,next;
 10 }Hash[maxn << 1];
 11 int flg[maxn + 66];
 12 int top,idx;
 13 //hash值插入
 14 void ins(int a,int b){
 15     int k = b & maxn;
 16     if(flg[k] != idx){
 17         flg[k] = idx;
 18         Hash[k].next = -1;
 19         Hash[k].a = a;
 20         Hash[k].b = b;
 21         return ;
 22     }
 23     while(Hash[k].next != -1){
 24         if(Hash[k].b == b) return ;
 25         k = Hash[k].next;
 26     }
 27     Hash[k].next = ++ top;
 28     Hash[top].next = -1;
 29     Hash[top].a = a;
 30     Hash[top].b = b;
 31 }
 32 //hash值查找
 33 int find(int b){
 34     int k = b & maxn;
 35     if(flg[k] != idx) return -1;
 36     while(k != -1){
 37         if(Hash[k].b == b) return Hash[k].a;
 38         k = Hash[k].next;
 39     }
 40     return -1;
 41 }
 42 int gcd(int a,int b)
 43 {
 44     return b?gcd(b,a%b):a;
 45 }
 46 int ext_gcd(int a,int b,int& x,int& y)
 47 {
 48     int t,ret;
 49     if (!b){x=1,y=0;return a;}
 50     ret=ext_gcd(b,a%b,x,y);
 51     t=x,x=y,y=t-a/b*y;
 52     return ret;
 53 }
 54 int Inval(int a,int b,int n){
 55     int x,y,e;
 56     ext_gcd(a,n,x,y);
 57     e=(LL)x*b%n;
 58     return e<0?e+n:e;
 59 }
 60 int pow_mod(LL a,int b,int c)
 61 {
 62     LL ret=1%c;
 63     a%=c;
 64     while(b){
 65         if(b&1)ret=ret*a%c;
 66         a=a*a%c;
 67         b>>=1;
 68     }
 69     return ret;
 70 }
 71 int BabyStep(int A,int B,int C){
 72     top = maxn; ++ idx;
 73     LL buf=1%C,D=buf,K;
 74     int i,d=0,tmp;
 75     for(i=0;i<=100;buf=buf*A%C,++i)
 76         if(buf==B)return i;
 77     while((tmp=gcd(A,C))!=1){
 78         if(B%tmp)return -1;
 79         ++d;
 80         C/=tmp;
 81         B/=tmp;
 82         D=D*A/tmp%C;
 83     }
 84     int M=(int)ceil(sqrt(C+0.5));
 85     for(buf=1%C,i=0;i<=M;buf=buf*A%C,++i)
 86         ins(i,buf);
 87     for(i=0,K=pow_mod((LL)A,M,C);i<=M;D=D*K%C,++i){
 88         tmp=Inval((int)D,B,C);
 89         int w ;
 90         if(tmp>=0&&(w = find(tmp)) != -1) return i*M+w+d;
 91     }
 92     return -1;
 93 }
 94 int main(){
 95     int A,B,C;
 96     while(scanf("%d%d%d",&A,&C,&B)!=EOF){
 97         if(B>C){
 98             puts("Orz,I can’t find D!");
 99             continue;
100         }
101         int tmp=BabyStep(A,B,C);
102         if(tmp<0)
103             puts("Orz,I can’t find D!");
104         else printf("%d\n",tmp);
105     }
106     return 0;
107 }
View Code

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。