BSGS和EXBSGS是OI中用于解决A^xΞB(mod C)的常用算法。

1.BSGS

BSGS用于A,C互质的情况。

令m=sqrt(C),此时x可表示为i*m+j。

式中i和j都<=sqrt(C)

原式Ax≡B(mode C) -->Ai*m * Aj≡B(mode C)

枚举Ai*m,此时Ai*m相当于系数。//O(sqrt(C))

现在我们可用exgcd/费马小定理求逆元算出Aj%C的值

通过预处理将A1~m存入map/哈希表。//O(1)//用map会多一个log

解决了。

时间复杂度O(sqrt(C)),思想类似meet_in_the_middle。

代码:

#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
ll fastpow(ll x,int y,int mod)
{
ll ret = 1ll;
while(y)
{
if(y&)ret=ret*x%mod;
x=x*x%mod;
y>>=;
}
return ret;
}
void ORZ(){printf("Orz, I cannot find x!\n");}
ll F2(ll y,int z,int p)
{
ll tmp = fastpow(y,p-,p);
tmp = tmp*z%p;
return tmp;
}
int hed[],cnt=;
struct EG
{
int to,w,nxt;
}e[];
void ae(int f,int t,int w)
{
e[++cnt].to = t;
e[cnt].w=w;
e[cnt].nxt = hed[f];
hed[f] = cnt;
}
int find(int x)
{
int now = x%;
for(int j=hed[now];j;j=e[j].nxt)
if(e[j].to==x)
return e[j].w;
return -;
}
void BSGS(ll y,int z,int p)
{
if(!y&&z){ORZ();return ;}
cnt=;
memset(hed,,sizeof(hed));cnt=;
ae(,,);
int m = (int)sqrt(p);
ll now = ;
for(int i=;i<=m;i++)
{
now = now*y%p;
if(find(now)==-)
{
ae(now%,now,i);
}
}
ll u = ;
for(int i=;i<=m+;i++)
{
ll tmp = F2(u,z,p);
ll ans = find(tmp);
if(~ans)
{
printf("%lld\n",(ans+i*m)%p);
return ;
}
u=u*now%p;
}
ORZ();
}
int T,K,y,z,p;
int main()
{
scanf("%d%d",&T,&K);
while(T--)
{
scanf("%d%d%d",&y,&z,&p);
y%=p;
if(K==)printf("%lld\n",fastpow(y,z,p));
else if(K==)
{
z%=p;
if(!y&&z){ORZ();continue;}
printf("%lld\n",F2(y,z,p));
}else
{
z%=p;
BSGS(y,z,p);
}
}
return ;
}

2.EXBSGS

EXBSGS用于解决C不一定是质数的问题。

对于方程Ax≡B(mode C)(gcd(A,C)!=1):

设d=gcd(A,C)。

如果B%d!=0的话,要么B==0,要么无解。

这时我们可以将三者同时/d,得到:

(A/d)*Ax-1≡ B/d (mode C/d)

此时A和C/d依然可能不互质(比如A=5,C=25)。

循环这个过程就可以啦。

我们最后得到的方程形式为:

(Ai/∏d)*Ax-i ≡ B/∏d(mode C/∏d)

其实就是D*Ax-i≡ B’(mode C’),然后套BSGS就好了。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
void ORZ()
{
printf("No Solution\n");
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=,y=;
return ;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
ll inv(ll a,ll b)
{
ll x,y;
exgcd(a,b,x,y);
return (x%b+b)%b;
}
ll gcd(ll x,ll y)
{
return y?gcd(y,x%y):x;
}
ll F2(ll y,ll z,ll p)
{
y%=p,z%=p;
ll ret = inv(y,p);
return ret*z%p;
}
int hed[],cnt;
struct EG
{
ll to,nxt,w;
}e[];
void ae(ll f,ll t,ll w)
{
e[++cnt].to = t;
e[cnt].nxt = hed[f];
e[cnt].w = w;
hed[f] = cnt;
}
ll find(ll x)
{
for(int j=hed[x%];j;j=e[j].nxt)
if(e[j].to==x)
return e[j].w;
return -;
}
ll BSGS(ll y,ll z,ll p)
{
memset(hed,,sizeof(hed));cnt=;
ae(,,);
y%=p,z%=p;
if(!y&&z)
{
ORZ();
return -;
}
ll now = 1ll,m = (ll)sqrt(p);
for(int i=;i<=m;i++)
{
now=now*y%p;
if(find(now)==-)
ae(now%,now,i);
}
ll u = 1ll;
for(int i=;i<=m+;i++)
{
ll tmp = F2(u,z,p);
ll ans = find(tmp);
if(~ans)
return ans+i*m;
u=u*now%p;
}
ORZ();
return -;
}
void EXBSGS(ll y,ll z,ll p)
{
if(!y&&z){ORZ();return ;}
if(z==){printf("0\n");return ;}
ll d = gcd(y,p),cnt=,D=1ll;
while(d!=)
{
if(z%d){ORZ();return ;}
cnt++;
z/=d,p/=d;
D=D*(y/d)%p;
d=gcd(y,p);
if(D==z){printf("%lld\n",cnt);return ;}
}
ll ans = BSGS(y,z*inv(D,p)%p,p);
if(ans!=-)printf("%lld\n",(ans+cnt)%p);
}
ll y,z,p;
int main()
{
while(scanf("%lld%lld%lld",&y,&p,&z))
{
if(!y&&!z&&!p)break;
EXBSGS(y,z,p);
}
return ;
}

模板BSGS(SDOI2011计算器) 模板EXBSGS的更多相关文章

  1. bzoj 2242: [SDOI2011]计算器 BSGS+快速幂+扩展欧几里德

    2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 你被 ...

  2. BZOJ 2242: [SDOI2011]计算器( 快速幂 + 扩展欧几里德 + BSGS )

    没什么好说的... --------------------------------------------------------------------- #include<cstdio&g ...

  3. BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS

    BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS 题意: 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p, ...

  4. BZOJ2242 [SDOI2011]计算器 【BSGS】

    2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 4741  Solved: 1796 [Submit][Sta ...

  5. 【洛谷 P2485】 [SDOI2011]计算器 (BSGS)

    题目链接 第一问:快速幂 第二问:扩欧解线性同余方程 第三问:\(BSGS\) 三个模板 #include <cstdio> #include <cmath> #include ...

  6. 【BZOJ2242】[SDOI2011]计算器 BSGS

    [BZOJ2242][SDOI2011]计算器 Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ ...

  7. 【bzoj2242】: [SDOI2011]计算器 数论-快速幂-扩展欧几里得-BSGS

    [bzoj2242]: [SDOI2011]计算器 1.快速幂 2.扩展欧几里得(费马小定理) 3.BSGS /* http://www.cnblogs.com/karl07/ */ #include ...

  8. BZOJ 2242: [SDOI2011]计算器 [快速幂 BSGS]

    2242: [SDOI2011]计算器 题意:求\(a^b \mod p,\ ax \equiv b \mod p,\ a^x \equiv b \mod p\),p是质数 这种裸题我竟然WA了好多次 ...

  9. bzoj 2242 [SDOI2011]计算器 快速幂+扩展欧几里得+BSGS

    1:快速幂  2:exgcd  3:exbsgs,题里说是素数,但我打的普通bsgs就wa,exbsgs就A了...... (map就是慢)..... #include<cstdio> # ...

  10. P2485 [SDOI2011]计算器

    P2485 [SDOI2011]计算器 题目描述 你被要求设计一个计算器完成以下三项任务: 1.给定y.z.p,计算y^z mod p 的值: 2.给定y.z.p,计算满足xy ≡z(mod p)的最 ...

随机推荐

  1. java如何遍历map的所有的元素(各种方法)

    JDK1.4中 Map map = new HashMap(); Iterator it = map.entrySet().iterator(); while (it.hasNext()) { Map ...

  2. 关于final修饰符

    一:修饰成员变量 关于被final修饰的成员属性(常量)初始化赋值问题分为以下两种情况: 1.被static修饰符修饰:可以通过两种途径进行初始化赋值 ① 在常量被定义时进行初始化赋值 ② 在静态代码 ...

  3. linux下系统调用劫持ioctl

    实验环境:linux 2.6.32   64位系统 采用lkm(动态加载内核模块)方式劫持ioctl系统调用,系统调用过程如图所示(以open为例子) 实验代码:(头文件有不需要的,但是懒得改了,在系 ...

  4. Swift4 模式, 枚举型

    创建: 2018/03/05 完成: 2018/03/05 更新: 2018/03/10 改变标题 [Swift4 模式] -> [Swift4 模式, 枚举型] 补充RawRepresenta ...

  5. mysql case 列名 when 和 case when的区别

    最近写了一个sql,才发现有些情况不能用case 列名 when ( and then and and 7.9 then '中' else '差' END ) score_type, 我发现这样写查出 ...

  6. Ubuntu An error occurred,please run Package Manager..

    转自https://blog.csdn.net/idealcitier/article/details/78294137 An error occurred,please run Package Ma ...

  7. python中threading模块中最重要的Tread类

    Tread是threading模块中的重要类之一,可以使用它来创造线程.其具体使用方法是创建一个threading.Tread对象,在它的初始化函数中将需要调用的对象作为初始化参数传入. 具体代码如下 ...

  8. 题解报告:hdu 4907 Task schedule

    Problem Description 有一台机器,并且给你这台机器的工作表,工作表上有n个任务,机器在ti时间执行第i个任务,1秒即可完成1个任务.有m个询问,每个询问有一个数字q,表示如果在q时间 ...

  9. 题解报告:hdu 2058 The sum problem

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2058 问题描述 给定一个序列1,2,3,...... N,你的工作是计算所有可能的子序列,其子序列的总 ...

  10. 题解报告:hdu 1261 字串数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1261 Problem Description 一个A和两个B一共可以组成三种字符串:"ABB ...