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

 

你可能感兴趣的:(ant)