1. 快速幂

  2. 扩展欧几里得

  3. baby-step-giant-step

可以自行baidu

程序附部分注释

  1 const key=1000007;
  2 type link=^node;
  3      node=record
  4        re,wh:longint;
  5        next:link;
  6      end;
  7 
  8 var hash:array[0..key] of link;
  9     a:array[0..100] of longint;
 10     j,g,ans,w,i,n,ch,t,p,z,y:longint;
 11     x,step,k,now:int64;
 12 
 13 function quick(y,z,p:longint):int64;
 14   var t,i:longint;
 15   begin
 16     quick:=1;
 17     t:=0;
 18     while z<>0 do
 19     begin
 20       inc(t);
 21       a[t]:=z mod 2;
 22       z:=z div 2;
 23     end;
 24     for i:=t downto 1 do
 25     begin
 26       quick:=sqr(quick) mod p;
 27       if a[i]=1 then quick:=quick*y mod p;
 28     end;
 29   end;
 30 
 31 function gcd(a,b:longint):longint;
 32   begin
 33     if b=0 then exit(a)
 34     else exit(gcd(b,a mod b));
 35   end;
 36 
 37 procedure exgcd(a,b:longint;var x,y:int64);  //扩展欧几里得
 38   var xx,yy:int64;
 39   begin
 40     if b=0 then
 41     begin
 42       x:=1;
 43       y:=0;
 44     end
 45     else begin
 46       exgcd(b,a mod b,x,y);
 47       xx:=x;
 48       yy:=y;
 49       x:=yy;
 50       y:=xx-(a div b)*yy;
 51     end;
 52   end;
 53 
 54 procedure add(x,i:longint);
 55   var p:link;
 56   begin
 57     w:=x mod key;
 58     p:=hash[w];
 59     while p<>nil do
 60     begin
 61       if p^.re=x then break;
 62       p:=p^.next;
 63     end;
 64     if p=nil then
 65     begin
 66       new(p);
 67       p^.re:=x;
 68       p^.wh:=i;
 69       p^.next:=hash[w];
 70       hash[w]:=p;
 71     end;
 72   end;
 73 
 74 function find(x:longint):longint;
 75   var p:link;
 76   begin
 77     find:=-1;
 78     w:=x mod key;
 79     p:=hash[w];
 80     while p<>nil do
 81     begin
 82       if p^.re=x then exit(p^.wh);
 83       p:=p^.next;
 84     end;
 85   end;
 86 
 87 begin
 88   readln(n,ch);
 89   for i:=1 to n do
 90   begin
 91     readln(y,z,p);
 92     if ch=1 then
 93       writeln(quick(y,z,p))  //快速幂不多说
 94     else if ch=2 then
 95     begin
 96       g:=gcd(y,p);
 97       if z mod g<>0 then   //先判断线性模方程是否有解
 98       begin
 99         writeln('Orz, I cannot find x!');
100         continue;
101       end;
102       y:=y div g;
103       p:=p div g;
104       z:=z div g;
105       exgcd(y,p,x,k);  //转化为二元一次不定方程
106       x:=((x*z mod p)+p) mod p;  //注意是最小非负数
107       writeln(x);
108     end
109     else begin
110       z:=z mod p;
111       t:=trunc(sqrt(p))+1;  当t选址为根号p时时间复杂度最优
112       for j:=0 to key do
113         hash[j]:=nil;
114       now:=1;
115       add(1,0);
116       for j:=1 to t do   //求出a^i mod p(0<=i<=t) 的值,并映射到hash上,每个模保留最小的i
117       begin
118         now:=now*y mod p;
119         add(now,j);
120       end;
121       g:=gcd(now,p);
122       if g<>1 then      //求出a^t关于mod p的逆元,没有逆元则无解
123       begin
124         writeln('Orz, I cannot find x!');
125         continue;
126       end
127       else begin
128         now:=now div g;
129         w:=p div g;
130       end;
131       exgcd(now,w,x,k);
132       x:=(x+w) mod w;
133       ans:=-1;
134       step:=z;
135       for j:=0 to t-1 do
136       begin
137         k:=find(step);   //大小步寻找  对于a^it ~ a^(i+1)t-1  (0<=i<=t-1) 寻找可行解
138 //存在可行解即存在hash中存在模=z*x^i mod p (x表示a^t的逆元) 
139         if k>-1 then
140         begin
141           ans:=k+j*t;
142           break;
143         end;
144         step:=step*x mod p;
145       end;
146       if ans=-1 then writeln('Orz, I cannot find x!')
147       else writeln(ans);
148     end;
149   end;
150 end.
View Code

 

posted on 2014-08-12 20:16  acphile  阅读(155)  评论(0编辑  收藏  举报