【bzoj2242】计算器——数论综合

终于在bzoj上AC一题了,虽然是看题解写的。。。

program sdoi2011;
const err='Orz, I cannot find x!';
      maxn=100000;
      maxm=2;
type re=record
         r,num:longint;
        end;

var gcd,a,b,c:int64;//convenient
    i,t,ty:longint;
    ha:array[0..maxn,0..maxm]of re;
function safe(x:int64):int64;
begin
 safe:=(x mod c+c) mod c;
end;

function mi(a,b:int64):int64;//a^b mod c
var y,ans:int64;
begin
 y:=a;
 ans:=1;
 while b<>0 do
  begin
   if b and 1=1 then ans:=ans*y mod c;
   y:=y*y mod c;
   b:=b shr 1;
  end;
 mi:=ans;
end;

procedure exgcd(a,b:int64;var x,y:int64);
begin
 if b=0 then
  begin
   x:=1;y:=0;
   gcd:=a;
   exit;
  end;
 exgcd(b,a mod b,y,x);
 y:=safe(y-a div b*x);
end;

procedure solve1;//ax+cy=gcd,ax+cy=b
var x,y:int64;
begin
 exgcd(a,c,x,y);
 if b mod gcd<>0 then
  begin
   writeln(err);
   exit;
  end;
 x:=safe(x);
 writeln(safe((b div gcd)*x));
end;

function inv(p:int64):int64;//p*x=1 (mod c)
var x,y:int64;
begin
 exgcd(p,c,x,y);
 if gcd=1 then exit((x+c) mod c) else exit(-1);
end;

procedure addhash(num,r:int64);
var hash,i:longint;
begin
 hash:=(num mod maxn+maxn) mod maxn;
 for i:=1 to maxm do
  begin
   if ha[hash,i].r>0 then continue;
   ha[hash,i].r:=r;
   ha[hash,i].num:=num;
   break;
  end;
end;
function inhash(b:int64;var post1,post2:int64):boolean;
var hash,i:longint;
begin
 hash:=(b mod maxn+maxn) mod maxn;
 for i:=1 to maxm do
  begin
   if ha[hash,i].r=0 then break;
   if ha[hash,i].num=b then
    begin
     post1:=hash;
     post2:=i;
     exit(true);
    end;
  end;
 exit(false);
end;

procedure solve2;//a^x=b (mod c) Baby Step Giant Step
var v,now,post1,post2:int64;
    i,m:longint;
begin
 b:=b mod c;
 fillchar(ha,sizeof(ha),0);
 m:=trunc(sqrt(c))+1;
 v:=inv(mi(a,m));//乘法逆
 now:=1;
 for i:=1 to m do
  begin
   now:=(now*a) mod c;
   addhash(now,i);
  end;
 for i:=0 to m-1 do
  begin
   if inhash(b,post1,post2) then
    begin
     writeln((i*m+ha[post1,post2].r) mod c);
     exit;
    end;
   b:=(b*v) mod c;
  end;
 writeln(err);
end;
begin
 read(t,ty);
 for i:=1 to t do
  begin
   read(a,b,c);
   case ty of
    1:writeln(mi(a,b));
    2:solve1;
    3:solve2;
   end;
  end;
end.


你可能感兴趣的:(【bzoj2242】计算器——数论综合)