【poj3243-Clever Y】高次同余方程-拓展BabyStepGiantStep
2016-02-04 08:30
288 查看
http://poj.org/problem?id=3243
题意:给定X,Z,K,求一个最小的Y满足XY mod Z = K。
关于拓展BSGS的详细解释我写了一篇博文:http://www.cnblogs.com/KonjakJuruo/p/5178600.html
题解:BSGS的拓展版本(因为X和Z不一定互质)。这道题挺坑的,如果K>=Z不是输出无解而是让K%=Z。
算是BSGS的模板题,我打了两种版本,就是二分查找和hash。对比两次提交来看,二分省空间,耗时间;Hash省时间,耗空间。
另外,find部分可以不用二分,而用hash解决。感觉大部分情况下还是hash比较快,但是比较耗空间。
把你需要存的数,即x的0~m次方算出来,假设是t,我们设m=1<<16-1,然后用t异或^m得nt(就是取t二进制后的15位进行hash),然后存到hash表里面去。如果t的位置目前没有存数,那么我们就直接存到hash[t]上去,如果t位置已经存了数(因为后15位为t的可能有多种情况),我们就在len除增加一个位置,把nt存到那里面去,然后hash[t].next=len,把位置记录下来,这应该就相当于一条链了。查找的时候循着这条链找下去即可,链的尽头的next用-1标记。
——引用自http://www.cnblogs.com/Konjakmoyu/p/5180458.html
BSGS-Hash
题意:给定X,Z,K,求一个最小的Y满足XY mod Z = K。
关于拓展BSGS的详细解释我写了一篇博文:http://www.cnblogs.com/KonjakJuruo/p/5178600.html
题解:BSGS的拓展版本(因为X和Z不一定互质)。这道题挺坑的,如果K>=Z不是输出无解而是让K%=Z。
算是BSGS的模板题,我打了两种版本,就是二分查找和hash。对比两次提交来看,二分省空间,耗时间;Hash省时间,耗空间。
另外,find部分可以不用二分,而用hash解决。感觉大部分情况下还是hash比较快,但是比较耗空间。
把你需要存的数,即x的0~m次方算出来,假设是t,我们设m=1<<16-1,然后用t异或^m得nt(就是取t二进制后的15位进行hash),然后存到hash表里面去。如果t的位置目前没有存数,那么我们就直接存到hash[t]上去,如果t位置已经存了数(因为后15位为t的可能有多种情况),我们就在len除增加一个位置,把nt存到那里面去,然后hash[t].next=len,把位置记录下来,这应该就相当于一条链了。查找的时候循着这条链找下去即可,链的尽头的next用-1标记。
——引用自http://www.cnblogs.com/Konjakmoyu/p/5180458.html
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; const LL N=40000,Max=(1<<16)-1; bool bk; LL X,Z,K,len; bool vis[70000]; struct node{ LL d,id,next; }hash[2*Max]; int exgcd(LL a,LL b,LL &x,LL &y) { if(b==0) {x=1,y=0;return a;} LL tx,ty; LL d=exgcd(b,a%b,tx,ty); x=ty;y=tx-(a/b)*ty; return d; } void ins(LL d,LL id) { LL t=d&Max; if(!vis[t]) { vis[t]=1; hash[t].d=d,hash[t].id=id,hash[t].next=-1; return ; } for(;hash[t].next!=-1;t=hash[t].next))//注意是hash[t].next!=-1 { if(hash[t].d==d) return; } hash[t].next=++len; hash[len].d=d;hash[len].id=id;hash[len].next=-1; } LL find(LL d) { LL t=d&Max; if(!vis[t]) return -1; for(;t!=-1;t=hash[t].next) { if(hash[t].d==d) return hash[t].id; } return -1; } LL BSGS() { LL t,g,x,y,pm,a,b,c,m,k,sum,am; a=X;b=K;c=Z;k=1;sum=0;t=1%c; for(int i=0;i<=100;i++){ if(t==b) return i; t=t*a%c; } while((g=exgcd(X,c,x,y))!=1) { k=(k*X/g)%c; c/=g; if(b%g) return -1; b/=g; sum++; } m=(LL)(ceil((double)sqrt((double)c))); ins(k,0); t=k;pm=1; for(int i=1;i<=m;i++) { t=t*a%c,pm=pm*a%c; ins(t,i); } exgcd(pm,c,x,y); am=x%c+c; t=b; for(int i=0;i<=m;i++) { x=find(t); if(x!=-1) return i*m+x+sum; t=t*am%c; } return -1; } int main() { // freopen("a.in","r",stdin); // freopen("b.out","w",stdout); while(1) { scanf("%I64d%I64d%I64d",&X,&Z,&K); if(!X && !Z && !K) return 0; K%=Z;len=Max; memset(vis,0,sizeof(vis)); LL ans=BSGS(); if(ans!=-1) printf("%I64d\n",ans); else printf("No Solution\n"); } return 0; }
BSGS-Hash
相关文章推荐
- LeetCode-55-Jump Game(贪心)-Medium
- centos vmware centos6.6 64位 kvm虚拟化安装配置 第四十二节课
- 工作半年总结
- 详谈京东的商品搜索系统架构设计
- 关闭钩子
- 学习asp.net比较完整的流程
- 全局获取Context的技巧
- [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下)
- Linux启动流程
- 使用Pelican在Github(国外)和Gitcafe(国内)同步托管博客
- 最优矩阵链乘
- Ubuntu下安装MySQL 5.6.23
- office 2010 你或管理员选择不安装宏或控件
- nodejs 更新本地 node_modules
- waitpid传入参数
- BZOJ 4282: 慎二的随机数列|动态规划
- JDK8 Stream API 学习
- Pelican+Github博客搭建详细教程
- 存储圈老炮大战小鲜肉
- Cmake常用指令