【Baby-step giant-step Algorithm】poj3243,hdu2815

有方程:a^x mod b = c;

已知a,b,c求一个最小的x

 

把式子变换为

a^(x'k+y) mod b = c >>

a^y mod b = c / a^(x'k)

 

我们可以枚举x',然后查找在a^(0~k-1)内是否有 c / a^(x'k) ,复杂度为 k+n/k,易知k为sqrt(n)时最优。

接下来的工作就是求a^(x'k)乘法逆元,由于b不是质数,不可以用欧拉函数,不过实际上我们是可以把bc的公因数提取出来的,提取出来之后就进入了一个phi(b/gcd(b,c))的循环节中,可以求逆元了,由于a^x不一定含有这个公因数所以之前要先朴素的运算到大约40左右(43是我学号,纯属蛋疼),在40次运算过后就进入这个循环节了,如果没有进入就肯定是No Solution 了。

 

 

program poj3243; const mom=1<<17-1; var d,next,x,y:array[0..mom] of longint; t,a,b,p,k,j,i,tt,mo,ny,ans,len:longint; ok:boolean; procedure ins(i,j:longint);var k:longint; begin inc(tt);k:=i and mom;next[tt]:=d[k];d[k]:=tt;x[tt]:=i;y[tt]:=j end; function gcd(a,b:longint):longint; begin if b=0 then exit(a) else exit(gcd(b,a mod b)) end; function fmul(mo,b:longint):int64; begin if b=0 then exit(1); fmul:=sqr(fmul(mo,b>>1))mod mo; if odd(b) then fmul:=fmul*a mod mo; end; function find(a:longint):longint;var k:longint; begin find:=-1;k:=d[a and mom]; while k<>0 do begin if (x[k]=a)and((find=-1)or(y[k]<find)) then find:=y[k]; k:=next[k]; end; end; function phi(a:longint):longint;var i:longint; begin i:=2;phi:=1; while i*i<=a do begin if a mod i=0 then begin a:=a div i;phi:=phi*(i-1); end; while a mod i=0 do begin a:=a div i;phi:=phi*i; end; inc(i); end; if a<>1 then phi:=phi*(a-1); end; begin readln(a,mo,b); while mo<>0 do begin p:=1;tt:=0;k:=gcd(mo,b); fillchar(d,sizeof(d),0); for ans:=0 to 43 do if p=b then break else p:=int64(p)*a mod mo; if p=b then writeln(ans) else if (a=0)or(b=0)or(gcd(mo div k,b)>1) then writeln('No Solution') else begin j:=k;i:=2;ok:=gcd(a,mo div k)>1; while i*i<=j do begin if not ok and(j mod i=0) then ok:=a mod i<>0; while j mod i=0 do j:=j div i; inc(i); end; if a mod j<>0 then ok:=true; if ok then writeln('No Solution') else begin t:=p;inc(ans); j:=phi(mo div k); len:=round(sqrt(j)); ny:=fmul(mo div k,j-len); for i:=0 to len-1 do begin ins(t,i);t:=int64(t)*a mod mo; end; while ans<=j+43 do begin t:=find(b); if t>=0 then break; inc(ans,len); b:=int64(b)*ny mod mo; end; if ans<=j+43 then writeln(t+ans) else writeln('No Solution'); end; end; readln(a,mo,b); end; end. 

你可能感兴趣的:(Algorithm,c,工作,div)