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. zabbix源码安装后,设置为服务启动和关闭

    zabbix源码安装,使用service启动与关闭服务 1. zabbix客户端的系统服务脚本 1.1 拷贝启动脚本 zabbix的源码提供了系统服务脚本,在/usr/local/src/zabbix ...

  2. 牛客网sql练习

    一建表语句 /* Navicat MySQL Data Transfer Source Server : test Source Server Version : 50717 Source Host ...

  3. Leetcode 174.地下城游戏

    地下城游戏 一些恶魔抓住了公主(P)并将她关在了地下城的右下角.地下城是由 M x N 个房间组成的二维网格.我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主. ...

  4. SQL Server 2008如何创建定期自动备份任务

    我们知道,利用SQL Server 2008数据库可以实现数据库的定期自动备份.方法是用SQL SERVER 2008自带的维护计划创建一个计划对数据库进行备份,下面我们将SQL SERVER 200 ...

  5. IE & table & border & border-collapse & bug

    shit IE table border bug & border-collapse bug > `border-collapse: collapse;` table { width: ...

  6. 567. Permutation in String

    Problem statement: Given two strings s1 and s2, write a function to return true if s2 contains the p ...

  7. 关于android系统启动不同activity默认过渡动画不同的一些认识

    在同一个android设备里,发现不同的app启动时显示的过渡动画是不同的.查看显示不同过渡动画的两个app的源码,其设置的主题都是同一个主题,但是为什么过渡动画效果不同呢?后来发现,activity ...

  8. key通用操作【九】

    一.概述: 在该系列的前几篇博客中,主要讲述的是与Redis数据类型相关的命令,如String.List.Set.Hashes和Sorted-Set.这些命令都具有一个共同点,即所有的操作都是针对与K ...

  9. 博弈论入门题 kiki's game

    Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his mind ...

  10. POJ 3276 Face The Right Way【枚举】

    题意: N头牛站成一条线,分别朝向前后两个方向,机器可以使连续K头牛同时改变方向,要求所有牛最终朝向前方,问机器操作次数的最小值及此时的最小K值. 分析: 第一眼看感觉是二分搜索K,再仔细读题, pl ...