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

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; typedef long long LL;
const int N=;
bool bk;
LL X,Z,K,a,b,c,m,k,sum,am,bl;
struct node{
LL d,id;
}bit[N],p[N]; bool cmp(node x,node y){
if(x.d!=y.d) return x.d<y.d;
return x.id<y.id;
} LL gcd(LL u,LL v)
{
if(v==) return u;
return gcd(v,u%v);
} LL find(LL x)
{
int l=,r=bl;
while(l<=r)
{
int mid=(l+r)>>;
if(bit[mid].d==x) return bit[mid].id;
if(bit[mid].d>x) r=mid-;
if(bit[mid].d<x) l=mid+;
}
return -;
} void exgcd(LL u,LL v,LL &x,LL &y)
{
if(v==) {x=,y=;return ;}
LL tx,ty;
exgcd(v,u%v,tx,ty);
x=ty;y=tx-(u/v)*ty;
return;
} LL BSGS()
{
LL t,g,x,y,pm;
a=X;b=K;c=Z;k=;sum=;bk=;bl=;t=%c;
for(int i=;i<=;i++){//避免a的负数次方
if(t==b) return i;
t=t*a%c;
}
while((g=gcd(X,c))!=)
{
k=(k*X/g)%c;//k记得要mod,否则溢出
c/=g;
if(b%g) return -;
b/=g;
sum++;
}
m=(LL)(ceil((double)sqrt((double)c)));//要约分之后再求m
p[].d=k%c;
p[].id=;
pm=;//pm是不用*k的
for(int i=;i<=m;i++)
p[i].d=p[i-].d*a%c,pm=pm*a%c,p[i].id=i;
sort(p,p++m,cmp);
bit[]=p[];bl=;
for(int i=;i<=m;i++)
{
if(p[i].d!=p[i-].d) bit[++bl]=p[i];
}
exgcd(pm,c,x,y);
am=(x%c+c);//避免am=0 t=b;
x=find(b);
if(x!=-) return x;
for(int i=;i<=bl;i++)
{
t*=am;t%=c;
x=find(t);
if(x!=-)
return i*m+x;
}
return -;
} int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
while()
{
scanf("%I64d%I64d%I64d",&X,&Z,&K);
if(!X && !Z && !K) return ;
K%=Z;
LL ans=BSGS();
if(ans!=-) printf("%I64d\n",ans+sum);
else printf("No Solution\n");
}
return ;
}

BSGS-二分

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; typedef long long LL;
const LL N=,Max=(<<)-;
bool bk;
LL X,Z,K,len;
bool vis[];
struct node{
LL d,id,next;
}hash[*Max]; int exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==) {x=,y=;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]=;
hash[t].d=d,hash[t].id=id,hash[t].next=-;
return ;
}
for(;hash[t].next!=-;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=-;
} LL find(LL d)
{
LL t=d&Max;
if(!vis[t]) return -;
for(;t!=-;t=hash[t].next)
{
if(hash[t].d==d) return hash[t].id;
}
return -;
} LL BSGS()
{
LL t,g,x,y,pm,a,b,c,m,k,sum,am;
a=X;b=K;c=Z;k=;sum=;t=%c;
for(int i=;i<=;i++){
if(t==b) return i;
t=t*a%c;
}
while((g=exgcd(X,c,x,y))!=)
{
k=(k*X/g)%c;
c/=g;
if(b%g) return -;
b/=g;
sum++;
}
m=(LL)(ceil((double)sqrt((double)c)));
ins(k,);
t=k;pm=;
for(int i=;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=;i<=m;i++)
{
x=find(t);
if(x!=-) return i*m+x+sum;
t=t*am%c;
}
return -;
} int main()
{
// freopen("a.in","r",stdin);
// freopen("b.out","w",stdout);
while()
{
scanf("%I64d%I64d%I64d",&X,&Z,&K);
if(!X && !Z && !K) return ;
K%=Z;len=Max;
memset(vis,,sizeof(vis));
LL ans=BSGS();
if(ans!=-) printf("%I64d\n",ans);
else printf("No Solution\n");
}
return ;
}

BSGS-Hash

【poj3243-Clever Y】高次同余方程-拓展BabyStepGiantStep的更多相关文章

  1. 【数论】【ex-BSGS】poj3243 Clever Y

    用于求解高次同余方程A^x≡B(mod C),其中C不一定是素数. http://blog.csdn.net/tsaid/article/details/7354716 这篇题解写得最好. 那啥,这题 ...

  2. 高次同余方程模板BabyStep-GiantStep

    /************************************* ---高次同余方程模板BabyStep-GiantStep--- 输入:对于方程A^x=B(mod C),调用BabySt ...

  3. poj3243 Clever Y[扩展BSGS]

    Clever Y Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8666   Accepted: 2155 Descript ...

  4. luogu2485 [SDOI2011]计算器 poj3243 Clever Y BSGS算法

    BSGS 算法,即 Baby Step,Giant Step 算法.拔山盖世算法. 计算 \(a^x \equiv b \pmod p\). \(p\)为质数时 特判掉 \(a,p\) 不互质的情况. ...

  5. 【hdu2815-Mod Tree】高次同余方程-拓展BadyStepGaintStep

    http://acm.hdu.edu.cn/showproblem.php?pid=2815 题意:裸题... 关于拓展BSGS的详细解释我写了一篇博文:http://www.cnblogs.com/ ...

  6. POJ 3243 Clever Y(离散对数-拓展小步大步算法)

    Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, ...

  7. 数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)

    什么叫高次同余方程?说白了就是解决这样一个问题: A^x=B(mod C),求最小的x值. baby step giant step算法 题目条件:C是素数(事实上,A与C互质就可以.为什么?在BSG ...

  8. [拓展Bsgs] Clever - Y

    题目链接 Clever - Y 题意 有同余方程 \(X^Y \equiv K\ (mod\ Z)\),给定\(X\),\(Z\),\(K\),求\(Y\). 解法 如题,是拓展 \(Bsgs\) 板 ...

  9. 『高次同余方程 Baby Step Giant Step算法』

    高次同余方程 一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法. ...

随机推荐

  1. netfilter

    http://jingyan.baidu.com/article/642c9d3415d2c9644a46f7c6.html http://blog.csdn.net/zhangskd/article ...

  2. Python3.x List方法集合

    Python中的一个内置的基础类型叫List,类比于OC中的Array..他是有序的,那么下面写一些基础的方法,以备需要时候查阅: 1>获取List的长度 len(List) 2> 索引访 ...

  3. 关于VS2010“ADO.NET Entity Data Model模板丢失或者添加失败问题

    我最近在安装vs2010后,添加ADO.NET Entity 实体时发现,我的新建项里面并没有这个实体模型,后来我就在博问里面发表了问题,请求大家帮忙解决,悲剧的是少有人回应啊,呵呵,不过我还是在网上 ...

  4. trap命令使用

    分享一个shell脚本技巧,大家写shell脚本的时候,一般而言仅仅保证功能可用,但程序的鲁棒性却不是太好,不够健壮,多数是脚本处理 一些中断信号导致,应对非预期的系统信号,其实系统自带的trap命令 ...

  5. Android -- PowerManager和PowerManager.WakeLock

    PowerManager.WakeLock                                                       PowerManager.WakerLock是我 ...

  6. oracle关于分区相关操作

    [sql] view plaincopy 1.查询当前用户下有哪些是分区表: SELECT * FROM USER_PART_TABLES; 2.查询当前用户下有哪些分区索引: SELECT * FR ...

  7. iptables端口转发

    iptables -t nat -A PREROUTING -d {外网ip}/32 -p tcp -m tcp --dport 4956 -j DNAT --to-destination 10.1. ...

  8. 《JavaScript高级程序设计》第3章 基本概念

    3.4 数据类型 3.4.1 typeof操作符 var message = 'some string'; console.log(typeof message); // 'string' conso ...

  9. HDU 5792 World is Exploding 树状数组+枚举

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5792 World is Exploding Time Limit: 2000/1000 MS (Ja ...

  10. 【BZOJ】【1041】【HAOI2008】圆周上的点

    数学 orz hzwer 完全不会做…… 很纠结啊,如果将来再遇到这种题,还是很难下手啊…… 引用题解: [分析]: 样例图示: 首先,最暴力的算法显而易见:枚举x轴上的每个点,带入圆的方程,检查是否 ...