https://www.zybuluo.com/ysner/note/1299836

定义

一种用来求解高次同余方程的算法。

一般问题形式:求使得\(y^x\equiv z(mod\ p)\)的最小非负\(x\)。

\(BSGS\)算法

要求\(p\)是质数。

由费马小定理可知,\(y^{p-1}\equiv1(mod\ p)\),所以暴力枚举只要枚举到\(p−1\)即可。

但是由于\(p\)一般都很大,所以一般都跑不动。。。

优化算法\(ing...\)

现在令\(x=mi−j\)(其中\(m=\lceil\sqrt p\rceil\))。

则方程可化为\(y^{mi-j}\equiv z(mod\ p)\),

\(y^{mi}\equiv y^jz(mod\ p)\)

然后可以发现\(j<m\)(否则\(x\)就是负数)

所以我们可以暴力枚举\(j\),与所得\(y^jz(mod\ p)\)的存在哈希表里,然后再暴力枚举\(i\),最后得出结果。

还要注意一些边界:

  • \(y!=0\)
  • \(z=1\)时\(puts("no\ solution")\)
  • \(i\)的边界是\([1,m+1]\)

一道Poj上的板子题

[SDOI2011]计算器

struct Hash_Table
{
int h[N],cnt;
struct Edge{int u,v,nxt;}e[N*10];
il void clear(){memset(h,-1,sizeof(h));cnt=0;}
il void add(re int u,re int v,re int w){e[++cnt]=(Edge){w,v,h[u]};h[u]=cnt;}
il int Query(re int x)
{
re int t=x%mod;
for(re int i=h[t];i+1;i=e[i].nxt)
if(e[i].u==x) return e[i].v;
return -1;
}
il void solve(re int y,re int z,re int p)
{
y%=p;z%=p;
if(!y) {puts("no solution");return;}
if(z==1) {puts("0");return;}
re int m=sqrt(p)+1;clear();
for(re int i=0,t=z;i<m;++i,t=1ll*t*y%p) add(t%mod,i,t);
for(re int i=1,tt=ksm(y,m,p),t=tt;i<=m+1;++i,t=1ll*t*tt%p)
{
re int j=Query(t);if(j==-1) continue;
printf("%d\n",i*m-j);return;
}
puts("no solution");
}
}BSGS;
int main()
{
re int y,p,z;
while(scanf("%d%d%d",&p,&y,&z)!=EOF)
{
BSGS.solve(y,z,p);
}
return 0;
}

拓展\(BSGS\)算法

不要求\(p\)是质数。

那就说明很可能\(gcd(y,p)!=1\),不满足费马小定理。

费马小定理提供了枚举上限,没有它这种问题就不好做了。。。

想想怎么把\(y,p\)约分。

令\(t=gcd(y,p)\)。

把方程改写成等式形式:$$y^x+kp=z$$

分析一下,可以发现\(z\)一定是\(t\)的倍数。

除\(t\):$$\frac{y}{t}y^{x-1}+\frac{p}{t}k=\frac{z}{t}$$

接下来再次检查\(gcd(y,\frac{z}{t})\)是否为\(1\),若否,说明还可以继续约分,理由同上。

最后形式为(那个\(t\)反正是个正整数)$$\frac{yk}{t}y{x-k}\equiv\frac{z}{t}(mod\ \frac{p}{t})$$

注意边界:

  • 如果\(t>1\)并且\(z\%t>0\),方程无解
  • 约分完的石子带到普通\(BSGS\)中时要带系数

咕谷模板题

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define il inline
#define re register
#define ll long long
#define fp(i,a,b) for(re int i=a;i<=b;++i)
#define fq(i,a,b) for(re int i=a;i>=b;--i)
using namespace std;
const int N=5e4,mod=45807;
il ll ksm(re ll S,re ll n,re int p)
{
re ll T=S;S=1;
while(n)
{
if(n&1) S=S*T%p;
T=T*T%p;
n>>=1;
}
return S;
}
struct Hash_Table
{
int h[N],cnt;
struct Edge{int u,v,nxt;}e[N*10];
il void clear(){memset(h,-1,sizeof(h));cnt=0;}
il void add(re int u,re int v,re int w){e[++cnt]=(Edge){w,v,h[u]};h[u]=cnt;}
il int Query(re int x)
{
re int t=x%mod;
for(re int i=h[t];i+1;i=e[i].nxt)
if(e[i].u==x) return e[i].v;
return -1;
}
il void solve(re int y,re int z,re int p)
{
if(z==1) {puts("0");return;}
re int k=0,a=1;
while(233)
{
re int t=__gcd(y,p);if(t==1) break;
if(z%t) {puts("No Solution");return;}
z/=t;p/=t;++k;a=1ll*a*y/t%p;
if(z==a) {printf("%d\n",k);return;}//有意思的地方
}
re int m=sqrt(p)+1;clear();
for(re int i=0,t=z;i<m;++i,t=1ll*t*y%p) add(t%mod,i,t);
for(re int i=1,tt=ksm(y,m,p),t=1ll*a*tt%p;i<=m+1;++i,t=1ll*t*tt%p)
{
re int j=Query(t);if(j==-1) continue;
printf("%d\n",i*m-j+k);return;
}
puts("No Solution");
}
}BSGS;
int main()
{
re int y,p,z;
while(scanf("%d%d%d",&y,&p,&z))
{
if(!p&&!y&&!z) break;
BSGS.solve(y,z,p);
}
return 0;
}

BSGS算法及拓展的更多相关文章

  1. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  2. BSGS算法

    BSGS算法 我是看着\(ppl\)的博客学的,您可以先访问\(ppl\)的博客 Part1 BSGS算法 求解关于\(x\)的方程 \[y^x=z(mod\ p)\] 其中\((y,p)=1\) 做 ...

  3. bzoj2242: [SDOI2011]计算器 && BSGS 算法

    BSGS算法 给定y.z.p,计算满足yx mod p=z的最小非负整数x.p为质数(没法写数学公式,以下内容用心去感受吧) 设 x = i*m + j. 则 y^(j)≡z∗y^(-i*m)) (m ...

  4. [BSGS算法]纯水斐波那契数列

    学弟在OJ上加了道"非水斐波那契数列",求斐波那契第n项对1,000,000,007取模的值,n<=10^15,随便水过后我决定加一道升级版,说是升级版,其实也没什么变化,只 ...

  5. BSGS算法及扩展

    BSGS算法 \(Baby Step Giant Step\)算法,即大步小步算法,缩写为\(BSGS\) 拔山盖世算法 它是用来解决这样一类问题 \(y^x = z (mod\ p)\),给定\(y ...

  6. uva11916 bsgs算法逆元模板,求逆元,组合计数

    其实思维难度不是很大,但是各种处理很麻烦,公式推导到最后就是一个bsgs算法解方程 /* 要给M行N列的网格染色,其中有B个不用染色,其他每个格子涂一种颜色,同一列上下两个格子不能染相同的颜色 涂色方 ...

  7. BSGS算法及其扩展

    bsgs算法: 我们在逆元里曾经讲到过如何用殴几里得求一个同余方程的整数解.而\(bsgs\)就是用来求一个指数同余方程的最小整数解的:也就是对于\(a^x\equiv b \mod p\) 我们可以 ...

  8. BSGS算法学习笔记

    从这里开始 离散对数和BSGS算法 扩展BSGS算法 离散对数和BSGS算法 设$x$是最小的非负整数使得$a^{x}\equiv b\ \ \ \pmod{m}$,则$x$是$b$以$a$为底的离散 ...

  9. bsgs算法详解

    例题  poj 2417bsgs  http://poj.org/problem?id=2417 这是一道bsgs题目,用bsgs算法,又称大小步(baby step giant step)算法,或者 ...

随机推荐

  1. chrome最强大的浏览器插件推荐,只要你会用其他的插件你可以删除了

    我们在学习和工作中经常会需要用到各种各样不同需求的插件,结果chrome插件越装越多,chrome浏览器也越来越慢!有时候链我们自己都懵圈了,一时间都想不起来这个插件是干什么用的.更可气的是,很多时候 ...

  2. FFmpeg加水印

    ffmpeg中文水印乱码两种原因 1.字符编码格式原因,中文必须是utf8编码格式的(我遇到的问题,在vs2013上写的中文,已做编码格式转码,放到centos7.2上编译运行也会出现中文乱码的问题, ...

  3. 洛谷 3106 [USACO14OPEN]GPS的决斗Dueling GPS's 3720 [AHOI2017初中组]guide

    [题解] 这两道题是完全一样的. 思路其实很简单,对于两种边权分别建反向图跑dijkstra. 如果某条边在某一种边权的图中不是最短路上的边,就把它的cnt加上1.(这样每条边的cnt是0或1或2,代 ...

  4. Springboot+dubbo+zookeeper整合

    本想自己搭建一个Spring+dubbo+zookeeper整合好的框架,想寻找个最佳实现但是遇到各种各样的问题,只好自己看看dubbo starter的源码 整理如下: 通过打上断点来看配置的对不对 ...

  5. Xcode报referenced from错误的总结

    一.库文件丢失 如果提示的文件是库文件,比如说是sdk的文件,有可能是就是丢失,或者没有引用到该工程. 1.点击这个.a库,或者framework,看右边的target里面是否引用到了当前的targe ...

  6. MYSQL Sorting result 把队列堆满了,该怎么办?

    show processlist;发现有200多个队列,select cardnum from table where xxxid = 31 order by abc_time desc 这样的一个排 ...

  7. PatentTips - Hierarchical RAID system including multiple RAIDs

    BACKGROUND OF THE INVENTION The present invention relates to a storage system offering large capacit ...

  8. spring mvc 访问静态资源404

    访问比如css js出现404提示 在spring的配置文件中加上如下代码即可 <!-- 静态资源404 --> <mvc:resources location="/res ...

  9. SQLServer2008 快捷键集合

    CTRL       +       SHIFT       +       B                 生成解决方案           CTRL       +       F7     ...

  10. jquery datatable显示隐藏子表

    <table id="parentTable">     <thead>         <tr>             <th> ...