您的位置:首页 > 其它

Discrete Logging hunnu10590 pku2417 fzu 1352 hit 1928 zoj 1898

2011-08-04 15:32 393 查看
以下转自:http://hi.baidu.com/aekdycoin/blog/item/b317ca18bb24334942a9ad55.html【普通BabyStepGiantStep】【问题模型】求解A^x=B(modC)中0<=x<C的解,C为素数【思路】我们可以做一个等价x=i*m+j(0<=i<m,0<=j<m)m=Ceil(sqrt(C))而这么分解的目的无非是为了转化为:(A^i)^m*A^j=B(modC)之后做少许暴力的工作就可以解决问题:(1)fori=0->m,插入Hash(i,A^imodC)(2)枚举i,对于每一个枚举到的i,令AA=(A^m)^imodC我们有AA*A^j=B(modC)显然AA,B,C均已知,而由于C为素数,那么(AA,C)无条件为1于是对于这个模方程解的个数唯一(可以利用扩展欧几里得或欧拉定理来求解)那么对于得到的唯一解X,在Hash表中寻找,如果找到,则返回i*m+j注意:由于i从小到大的枚举,而Hash表中存在的j必然是对于某个剩余系内的元素X是最小的(就是指标)所以显然此时就可以得到最小解如果需要得到x>0的解,那么只需要在上面的步骤中判断当i*m+j>0的时候才返回到目前为止,以上的算法都不存在争议,大家实现的代码均相差不大。可见当C为素数的时候,此类离散对数的问题可以变得十分容易实现。#include<stdio.h> #include<math.h> #include<stdlib.h> #definenmax46341 #defineLLlonglong typedefstructNum{ intnnum; intii; }Num; Numnum[nmax]; intx,y; intcmp(constvoid*a,constvoid*b){ Num*n=(Num*)a; Num*m=(Num*)b; if(n->nnum>m->nnum){ return1; } return-1; } intextend_gcd(inta,intb){ if(b==0){ x=1,y=0; returna; } intd=extend_gcd(b,a%b); inttx=x; x=y; y=tx-a/b*y; returnd; } intfind_num(intx,intn){ intmid,left,right; left=0,right=n+1; while(left<=right){ mid=(left+right)>>1; if(num[mid].nnum==x){ returnnum[mid].ii; }elseif(num[mid].nnum>x){ right=mid-1; }else{ left=mid+1; } } return-1; } intmain(){ #ifndefONLINE_JUDGE freopen("t.txt","r",stdin); freopen("out.txt","w",stdout); #endif LLptemp,te; inti,j,pte,p,b,n,bb,temp; while(scanf("%d%d%d",&p,&b,&n)!=EOF){ pte=(int)((sqrt(p*1.0)+0.5)); for(i=0,ptemp=1;i<=pte;i++){ num[i].nnum=(int)(ptemp); num[i].ii=i; ptemp=ptemp*b%p; } bb=num[pte].nnum; qsort(num,pte+1,sizeof(num[0]),cmp); for(i=0,ptemp=1;i<=pte;i++){ temp=(int)(ptemp); extend_gcd(temp,p); te=(int)(x); te=te*n; te=te%p+p; x=(int)(te%p); j=find_num(x,pte); if(j!=-1){ printf("%d\n",pte*i+j); break; } ptemp=ptemp*bb%p; } if(i>pte){ printf("ERROR\n"); } } return0; }hunnu10590fzu1352pku2417hit1928zoj1898
/*a^x=b(modc)cisprime*/#include<stdio.h>#include<math.h>#include<string.h>#include<stdlib.h>#defineLLlonglong#definenmax46345typedefstructnum{intii,value;}num;numNum[nmax];intx,y;intcmp(constvoid*a,constvoid*b){numn=*(num*)a;numm=*(num*)b;returnn.value-m.value;}voidextend_gcd(inta,intb){intxx;if(b==0){x=1,y=0;return;}extend_gcd(b,a%b);xx=x;x=y,y=xx-a/b*y;}intbfindNum(intkey,intn){intleft,right,mid;left=0,right=n;while(left<=right){mid=(left+right)>>1;if(Num[mid].value==key){returnNum[mid].ii;}elseif(Num[mid].value>key){right=mid-1;}else{left=mid+1;}}return-1;}voidsolve(intc,inta,intb){inti,j,te,aa;LLtemp,xx;te=(int)(sqrt(c*1.0)+0.5);for(i=0,temp=1%c;i<=te;i++){Num[i].ii=i;Num[i].value=(int)(temp);temp=temp*a%c;}aa=Num[te].value;qsort(Num,te+1,sizeof(Num[0]),cmp);for(i=0,temp=1;i<=te;i++){extend_gcd((int)(temp),c);xx=(LL)x;xx=xx*b;xx=xx%c+c;x=(int)(xx%c);j=bfindNum(x,te+1);if(j!=-1){printf("%d\n",i*te+j);return;}temp=temp*aa%c;}puts("nosolution");}intmain(){#ifndefONLINE_JUDGEfreopen("data.in","r",stdin);#endifintp,b,n;while(~scanf("%d%d%d",&p,&b,&n)){solve(p,b,n);}return0;}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: