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. vi常用设置

    vi不能使用退格键和上下左右键 因为ubuntu默认安装的是vim-tiny,所以需要安装完整版本 apt-get install vim 安装完再使用就可以了 vi本身是不带颜色的,vim带颜色,使 ...

  2. bzoj 3930: [CQOI2015]选数【递推】

    妙啊 这个题一上来就想的是莫比乌斯反演: \[ f(d)=\sum_{k=1}^{\left \lceil \frac{r}{d} \right \rceil}\mu(k)(\left \lceil ...

  3. VS2010编译错: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0403...的解决方法

        最近拿到一个别人的工程,是使用VS.net创建的,而我的机器上只有vs2010,于是用自带的转换工具将它转换成vs2010的工程,转换之前我就很担心,怕转换完后会出问题,但是没有办法,我实在是 ...

  4. SQL 初级教程学习(五)

    1.DEFAULT 约束用于向列中插入默认值. CREATE TABLE Orders(Id_O int NOT NULL,OrderNo int NOT NULL,Id_P int,OrderDat ...

  5. [POJ1721]Cards

    Description 剀剀和凡凡有N张牌(依次标号为1,2,--,N)和一台洗牌机.假设N是奇数.洗牌机的功能是进行如下的操作:对所有位置I(1≤I≤N),如果位置I上的牌是J,而且位置J上的牌是K ...

  6. poj 3295 Tautology 伪递归

    题目链接: http://poj.org/problem?id=3295 题目描述: 给一个字符串,字符串所表示的表达式中p, q, r, s, t表示变量,取值可以为1或0.K, A, N, C, ...

  7. Ignatius and the Princess III HDU - 1028 || 整数拆分,母函数

    Ignatius and the Princess III HDU - 1028 整数划分问题 假的dp(复杂度不对) #include<cstdio> #include<cstri ...

  8. 命名管道实现进程间通信--石头、剪刀、布游戏 分类: linux 2014-06-01 22:50 467人阅读 评论(0) 收藏

    下面这个程序利用命名管道实现进程间通信,模拟石头剪刀布游戏. 主进程为裁判进程,两个子进程为选手进程.裁判与选手间各建立一个命名管道. 进行100次出招,最后给出游戏胜负. #include < ...

  9. 转-关于UIView的autoresizingMask属性的研究

    在 UIView 中有一个autoresizingMask的属性,它对应的是一个枚举的值(如下),属性的意思就是自动调整子控件与父控件中间的位置,宽高. 1 2 3 4 5 6 7 8 9 enum  ...

  10. 414 Third Maximum Number 第三大的数

    给定一个非空数组,返回此数组中第三大的数.如果不存在,则返回数组中最大的数.要求算法时间复杂度必须是O(n).示例 1:输入: [3, 2, 1]输出: 1解释: 第三大的数是 1.示例 2:输入: ...