BSGS及其拓展

BSGS

介绍

这是一个求解ax≡b(modp)a ^ {x} \equiv b \pmod paxb(modp),的方法。并且ppp是质数,a,pa, pa,p互质,费马小定理可知,这个式子有周期性,

我们一般取m=sqrt(p)m = sqrt(p)m=sqrt(p),假设x=i∗m+j,0<=i,j<=mx = i * m + j, 0 <= i, j <= mx=im+j0<=i,j<=m,则有

ai∗m+j≡b(modp)a ^ {i * m + j} \equiv b \pmod paim+jb(modp)

ai+m≡baj(modp)a ^ {i + m} \equiv \frac {b} {a ^ j} \pmod pai+majb(modp)

为了方便我们设x=i∗m−jx = i * m - jx=imj,则有

ai∗m≡b∗aj(modp)a ^ {i * m} \equiv b * a ^ {j} \pmod paimbaj(modp)

所以我们只要通过一次枚举jjj,记录下b∗ajb * a ^ jbaj,再一次枚举iii去刚才枚举过的jjj中寻找有没有符合要求的答案即可,整体复杂度是p\sqrt {p}p

P2485 [SDOI2011]计算器

模板题

/*Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>// #include <cstdio>
// #include <iostream>
// #include <stdlib.h>
// #include <algorithm>
// #include <cmath>#define mp make_pair
#define pb push_back
#define endl '\n'using namespace std;typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;inline ll read() {ll f = 1, x = 0;char c = getchar();while(c < '0' || c > '9') {if(c == '-')    f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f * x;
}void print(ll x) {if(x < 10) {putchar(x + 48);return ;}print(x / 10);putchar(x % 10 + 48);
}ll quick_pow(ll a, ll n, ll mod) {ll ans = 1;while(n) {if(n & 1) ans = (ans * a) % mod;n >>= 1;a = (a * a) % mod;}return ans;
}ll quick_mult(ll a, ll b, ll mod) {ll ans = 0;while(b) {if(b & 1) ans = (ans + a) % mod;b >>= 1;a = (a + a) % mod;}return ans;
}ll ex_gcd(ll a, ll b, ll & x, ll & y) {if(!b) {x = 1, y = 0;return a;}ll gcd = ex_gcd(b, a % b, x, y);ll temp = x;x = y;y = temp - a / b * y;return gcd;
}void BSGC(ll a, ll b, ll p) {map<ll, ll> MP;int m = sqrt(p) + 1;ll x = b, nex = quick_pow(a, m, p);for(int i = 0; i <= m; i++) {MP[x] = i;x = (x * a) % p;}x = 1;if(nex == 0) {if(b == 0) {puts("0");}else {puts("Orz, I cannot find x!");}return ;}for(int i = 0; i <= m; i++) {if(MP.count(x)) {printf("%d\n", i * m - MP[x]);return ;}x = (x * nex) % p;}puts("Orz, I cannot find x!");
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n = read(), k = read();for(int i = 1; i <= n; i++) {ll a = read(), b = read(), p = read();if(k == 1) {printf("%lld\n", quick_pow(a, b, p));}else if(k == 2) {ll x, y;ll gcd = ex_gcd(a, p, x, y);if(b % gcd) {puts("Orz, I cannot find x!");}else {b /= gcd;x = (((x % p + p) % p) * b) % p;printf("%lld\n", x);}}   else {BSGC(a, b % p, p);}}return 0;
}

2019牛客暑期多校训练营(第五场)C generator 2

思路

x0=x0x_0 = x_0x0=x0

x1=a∗x0∗bx_1 = a * x_0 * bx1=ax0b

x2=a∗x1+b=a2∗x0+a∗b+bx_2 = a * x_1 + b = a ^{2} * x_0 + a * b + bx2=ax1+b=a2x0+ab+b

容易发现后项是一个等比数列求和

xn=anx0+b(1−an)1−ax_n = a ^ {n} x_0 + \frac {b (1 - a ^ n)} {1 - a}xn=anx0+1ab(1an)

我们要求xn=vx_n = vxn=v,化简

anx0+b(1−an)1−a=va ^ {n} x_0 + \frac {b (1 - a ^ n)} {1 - a} = vanx0+1ab(1an)=v

anx0(1−a)+b(1−an)=v(1−a)a ^{n} x_0(1 - a) + b (1 - a ^ n) = v(1 - a)anx0(1a)+b(1an)=v(1a)

an(x0−ax0−b)=v(1−a)−ba ^ n (x_0 - ax_0 - b) = v(1 - a) - ban(x0ax0b)=v(1a)b

an=v(1−a)−bx0−ax0−ba^n =\frac {v (1 - a) - b} {x_0 - a x_0 - b}an=x0ax0bv(1a)b

上面式子都是modp\mod pmodp下的同余等式,为了方便写了===

看到这里就简单了,我们要求解的是nnn,显然右边这一坨都是已知的,我们假定为BBB,求解an=Ba ^ n = Ban=B,这不就是个裸题了吗。

这道题目还要稍加分类讨论一下:

  • a == 0

x0=x0,xi=b(i>=1)x_0 = x_0, x_i = b(i >= 1)x0=x0,xi=b(i>=1)

  • a==1a == 1a==1

因为这种情况上面不能直接相除,所以我们需要特殊考虑ai=b+i∗aa_i = b + i * aai=b+ia

也就是求解i∗a=v−bi * a = v - bia=vb,这个时候只要左右两边同时乘以aaa的逆元即可得到我们要的iii

代码

/*Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define endl '\n'using namespace std;typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;inline ll read() {ll f = 1, x = 0;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f * x;
}void print(ll x) {if(x < 10) {putchar(x + 48);return ;}print(x / 10);putchar(x % 10 + 48);
}ll quick_pow(ll a, ll n, ll mod) {ll ans = 1;while(n) {if(n & 1) ans = (ans * a) % mod;a = (a * a) % mod;n >>= 1;}return ans;
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int T = read();while(T--) {ll n = read(), x0 = read(), a = read(), b = read(), p = read();ll x = 1, Unit = quick_pow(a, 1000, p);unordered_map<ll, int> MP;for(int i = 1; i <= 1000000; i++) {x = (x * Unit) % p;if(!MP.count(x)) {MP[x] = i * 1000;}}ll inv = quick_pow(((x0 - a * x0 - b) % p + p) % p, p - 2, p);int t = read();while(t--) {ll v = read();if(a == 0) {if(v % p == x0 % p) {puts("0");}else if(v % p == b % p) {puts("1");}else {puts("-1");}continue;}if(a == 1) {ll ans = (((((v - x0) % p + p) % p) * quick_pow(b, p - 2, p))) % p;if(ans < n) {printf("%lld\n", ans);}else {puts("-1");}continue;}v = (((v * (1 - a) - b) % p + p) % p * inv) % p;if(Unit == 0) {if(v == 0) {puts("0");}else {puts("-1");}continue;}x = v;int ans = p + 1;for(int i = 0; i <= 1000; i++) {if(MP.count(x)) {ans = min(ans, MP[x] - i);}x = (x * a) % p;}if(ans != p + 1 && ans < n) {printf("%d\n", ans);}else {puts("-1");}}}return 0;
}

BSGS拓展

介绍

求解ax≡b(modp)a ^ x \equiv b \pmod paxb(modp),但是a,ba, ba,b不互质,这里就要用到我们的EXBSGSEXBSGSEXBSGS了。

假定ax+py=ba ^ x + py = bax+py=b

d1=gcd(a,p),如果有解则一定:gcd(a,p)∣bd_1 = gcd(a, p),如果有解则一定:gcd(a, p) \mid bd1=gcd(a,p)gcd(a,p)b

得到ax−1ad1+pd1y=bd1a ^{x - 1}\frac{a} {d_1} + \frac{p}{d_1}y = \frac {b} {d_1}ax1d1a+d1py=d1b

如果gcd(a,pd1)!=1gcd(a, \frac{p} {d_1}) != 1gcd(a,d1p)!=1,继续化简

d2=gcd(a,pd1)−>ax−2a2d1d2+pd1d2y=bd1d2d_2 = gcd(a, \frac{p} {d_1})->a ^{x - 2} \frac{a ^ 2} {d_1d_2} + \frac{p} {d_1d_2}y = \frac{b}{d_1d_2}d2=gcd(a,d1p)>ax2d1d2a2+d1d2py=d1d2b

如果gcd(a,p2d1d2)!=1gcd(a, \frac{p ^ 2} {d_1d_2}) != 1gcd(a,d1d2p2)!=1

重复上面操作,最后得到式子

ax−nand1d2……dn+pd1d2……dny=bd1d2……dna ^{x - n} \frac {a ^ n} {d_1d_2……d_n} + \frac{p}{d_1d_2……d_n}y = \frac{b}{d_1d_2……d_n}axnd1d2dnan+d1d2dnpy=d1d2dnb

A=ax−n,A′=and1d2……dn,P=pd1d2……dn,B=bd1d2……dnA = a {x - n}, A' = \frac{a^n}{d_1d_2……d_n}, P = \frac{p}{d_1d_2……d_n}, B = \frac{b} {d_1d_2……d_n}A=axn,A=d1d2dnan,P=d1d2dnp,B=d1d2dnb

则变成里求Ax−n≡BA′−1(modP)A^{x - n} \equiv B A'^{-1} \pmod{P}AxnBA1(modP)

记录进行了多少次gcdgcdgcd求解,通过求A′A'A的逆元化简式子,再通过一次BSGSBSGSBSGS求得x−nx - nxn,即可得到我们得答案xxx

P4195 【模板】扩展BSGS

一定注意求逆元不能用费马小定理,我就入了这个坑。

/*Author : lifehappy
*/
#include <bits/stdc++.h>using namespace std;typedef long long ll;ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;
}ll quick_pow(ll a, ll n, ll mod) {ll ans = 1;while(n) {if(n & 1) ans = (ans * a) % mod;a = (a * a) % mod;n >>= 1;}return ans;
}int exgcd(int a, int b, int & x, int & y) {if(!b) {x = 1, y = 0;return a;}int gcd = exgcd(b, a % b, x, y);int temp = x;x = y;y = temp - a / b * y;return gcd;
}int inv(int a, int b) {int x, y;exgcd(a, b, x, y);return (x % b + b) % b;
}int BSGS(ll a, ll b, ll p) {int m = sqrt(p) + 1;unordered_map<int, int> mp;int x = b;for(int i = 0; i <= m; i++) {mp[x] = i;x = (1ll * x * a) % p;}x = 1;int Unit = quick_pow(a, m, p);if(Unit == 0) {if(b == 0) {return 0;}else {return -1;}}for(int i = 1; i <= m; i++) {x = (1ll * x * Unit) % p;if(mp.count(x)) {return i * m - mp[x];}}return -1;
}void EXBSGS(ll a, ll b, ll p) {a %= p, b %= p;if(b == 1 || p == 1) {puts("0");return ;}int cnt = 0, d, ad = 1;while((d = gcd(a, p)) != 1) {if(b % d) {puts("No Solution");return ;}cnt++;b /= d, p /= d;ad = (1ll * ad * a / d) % p;if(ad == b) {printf("%d\n", cnt);return ;}}int ans = BSGS(a % p, (1ll * b * inv(ad, p)) % p, p);if(ans == -1) {puts("No Solution");}else {printf("%d\n", ans + cnt);}
}int main() {// freopen("in.txt", "r", stdin);ll a, b, p;while(scanf("%lld %lld %lld", &a, &p, &b) && (a || b || p)) {EXBSGS(a, b, p);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF 1642 F. Two Arrays 随机 + sosdp

文章目录题意思路传送门 题意 给你nnn个长度为mmm的数组&#xff0c;每个数组都有一个价值wiw_iwi​&#xff0c;让你选出两个数组他们没有交集且价值和最大&#xff0c;如果没有输出−1-1−1。 2≤n≤1e5,1≤m≤5,1≤ai,j,wi≤1e92\le n\le 1e5,1\le m\le 5,1\le a_{i,j},w_…

你必须知道的Dockerfile

本篇已加入《.NET Core on K8S学习实践系列文章索引》&#xff0c;可以点击查看更多容器化技术相关系列文章。本文预计阅读时间为5分钟。01—关于Dockerfile在Docker中创建镜像最常用的方式&#xff0c;就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件&#xff0c;我…

2019牛客暑期多校训练营(第五场)C generator 2 (BSGS)

2019牛客暑期多校训练营&#xff08;第五场&#xff09;C generator 2 思路 x0x0x_0 x_0x0​x0​ x1a∗x0∗bx_1 a * x_0 * bx1​a∗x0​∗b x2a∗x1ba2∗x0a∗bbx_2 a * x_1 b a ^{2} * x_0 a * b bx2​a∗x1​ba2∗x0​a∗bb 容易发现后项是一个等比数列求和 xnanx0…

RabbitMQ 死信/死信队列

一、RabbitMQ 死信/死信队列1、DLXDead Letter Exchange 的缩写DLX&#xff08;Dead Letter Exchanges&#xff09;死信交换&#xff0c;死信队列本身也是一个普通的消息队列&#xff0c;在创建队列的时候&#xff0c;通过设置一些关键参数&#xff0c;可以将一个普通的消息队列…

AtCoder Regular Contest 059

文章目录C - Be TogetherD - UnbalancedE - Children and CandiesF - Unhappy Hacking题目链接 C - Be Together 200200200分 结论 直接取所有数的平均数&#xff0c;由于需要是整数&#xff0c;所以算一下mid,mid1,mid−1mid,mid1,mid-1mid,mid1,mid−1&#xff0c;取最小值…

P2303 [SDOI2012] Longge 的问题

P2303 [SDOI2012] Longge 的问题 思路 我们显然可以枚举每一对数的gcdgcdgcd进行求解&#xff0c;进而我们有如下推导&#xff1a; >∑i1ngcd(i,n)>\sum _{i 1} ^ {n} gcd(i, n)>i1∑n​gcd(i,n) >∑d∣nd∑i1n(gcd(i,d)d)>\sum _{d \mid{n}} d \sum _{i 1}…

centos7 rabbitmq安装/配置

一、RabbitMQ简单介绍RabbitMQ就是当前最主流的消息中间件之一。RabbitMQ是一个开源的AMQP实现&#xff0c;服务器端用Erlang语言编写&#xff0c;支持多种客户端&#xff0c;如&#xff1a;Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等&#xff0c;支…

Xor Path

Xor Path 思路 先是看错题目&#xff0c;以为是所有的路径异或值的和&#xff0c;然后好像用了个假的print函数&#xff0c;一直wa&#xff0c;&#xff0c;&#xff0c; 既然是异或&#xff0c;那么当一个点出现的次数是偶数次的时候它会被自己异或成零&#xff0c;也就是队…

CF 1642 E. Anonymity Is Important 线段树 + 离线

文章目录题意思路传送门 题意 有nnn个人&#xff0c;给你qqq个请求&#xff0c;分以下三种&#xff1a; [l,r,x][l,r,x][l,r,x] 如果x0x0x0&#xff0c;代表[l,r][l,r][l,r]这个区间内的人都没病。[l,r,x][l,r,x][l,r,x] 如果x1x1x1&#xff0c;代表[l,r][l,r][l,r]这个区间内…

Hyper-V + CentOS7 安装视频教程

一、前言本文使用图文视频的方式展示安装Centos7&#xff0c;【喜欢看视频学习的童靴请拖至文尾观看视频】二、虚拟机配置指定虚拟机名称&安装位置选择虚拟机代数 第一代虚拟机&#xff08;例如Server 2008等平台技术&#xff0c;支持Vista、Win7&#xff09; 第二代虚拟机…

SP5971 LCMSUM - LCM Sum

SP5971 LCMSUM - LCM Sum 思路 ∑i1nlcm(i,n)\sum_{i 1}^{n}lcm(i, n)i1∑n​lcm(i,n) >∑i1ningcd(i,n)> \sum_{i 1}^{n}\frac{i n}{gcd(i, n)}>i1∑n​gcd(i,n)in​ >n∑i1nigcd(i,n)> n\sum_{i 1}^{n}\frac{i}{gcd(i, n)}>ni1∑n​gcd(i,n)i​ 我们按…

程序员修神之路--用NOSql给高并发系统加速

领取福利记得长按&#xff0c;领取技术书籍哦随着互联网大潮的到来&#xff0c;越来越多网站&#xff0c;应用系统需要海量数据的支撑&#xff0c;高并发、低延迟、高可用、高扩展等要求在传统的关系型数据库中已经得不到满足&#xff0c;或者说关系型数据库应对这些需求已经显…

欧拉函数的性质及其证明

欧拉函数 ppp是素数&#xff0c;则有ϕ(p)p−1\phi(p) p - 1ϕ(p)p−1 证明&#xff1a;显然。 ppp是素数&#xff0c;npkn p ^ knpk&#xff0c;则ϕ(n)pk−pk−1\phi(n) p ^ k - p ^ {k - 1}ϕ(n)pk−pk−1 证明&#xff1a; [1,n][1, n][1,n]内&#xff0c;ppp的约数有p…

AtCoder Regular Contest 061

文章目录C - Many FormulasD - Snukes ColoringE - Snukes Subway TripF - Card Game for Three传送门 C - Many Formulas Score : 300300300 points 爆搜 直接dfsdfsdfs爆搜即可 复杂度O(2n)O(2^n)O(2n) 代码 D - Snuke’s Coloring Score : 400400400 points 考虑有标…

限时团购,6.5折:《C# 7.0 核心技术指南》

大家好&#xff0c;经过近两年的翻译&#xff0c;《C# 7.0 核心技术指南》终于和大家见面了。全书由 ThoughtWorks 高级咨询师&#xff0c;资深 .NET 专家刘夏翻译。作为一本第七次再版的图书&#xff0c;此次翻译对书中的字句进行了重新整理。期间和图书的原作者 Joe Albahari…

小A的最短路

小A的最短路 思路 树上问题求两个点的最短距离&#xff0c;显然能用lcalcalca来进行lognlog_nlogn​的查询&#xff0c;引入了两个无边权的点&#xff0c;所以我们的路劲就可以规划成三种x−>y&#xff0c;x−>u−>v−>y&#xff0c;x−>v−>u>−yx -&g…

Codeforces Beta Round #11 B. Jumping Jack 思维

文章目录题意&#xff1a;思路&#xff1a;传送门 题意&#xff1a; 初始在000点&#xff0c;第iii次跳跃可以跳iii的距离&#xff0c;可以选择向右或者向左跳&#xff0c;求最少多少次可以跳到xxx点。 −1e9≤x≤1e9-1e9\le x\le 1e9−1e9≤x≤1e9 思路&#xff1a; 我们贪…

Azure 命令行工具大混战,都是什么,该选哪个?

点击上方蓝字关注“汪宇杰博客”导语最近在学习 Azure 的命令行玩法&#xff0c;发现官方有不止一种命令行工具&#xff0c;容易对新手产生混淆&#xff0c;本文将介绍各种工具都是干啥的&#xff0c;以及如何选择。目前&#xff0c;微软官方有3个Azure命令行工具&#xff0c;分…

HDU 2588 GCD(欧拉函数)

GCD 思路 题目要求&#xff0c;对于给定的n,mn, mn,m要求有多少数∑i1ngcd(i,n)>m\sum _{i 1} ^{n} gcd(i, n) > m∑i1n​gcd(i,n)>m 我们可以对这个式子进行化简&#xff0c;通过枚举dgcd(i,n)d gcd(i, n)dgcd(i,n)有 ∑d∣n∑i1ngcd(i,d)d\sum _{d \mid n} \su…

2021 ccpc 哈尔滨 G. Damaged Bicycle 状压 + 期望dp

文章目录题意&#xff1a;思路&#xff1a;传送门 题意&#xff1a; 你需要从111走到nnn&#xff0c;初始速度是ttt&#xff0c;某些地方有自行车&#xff0c;每个位置自行车有pip_ipi​的概率是坏掉的&#xff0c;如果自行车没坏可以骑上自行车&#xff0c;速度是rrr&#x…