BSGS
BSGS
本质是根号分治
- 用途:求解\(A^x\equiv B\pmod p\)(a,p互质)
- 做法:将\(x\)变为\(im-j\),则原式变为\(A^{im}\equiv BA^j \pmod p\)。枚举j,将每一个\(BA^j\)插入hash中,然后再枚举i,查询\(a^{im}\)是否出现,若出现,返回\(im-j\)。注意特判,当\(A\bmod p =0 \& B\bmod p = 0\)时,为1,当\(A\bmod p =0 \& B\bmod p \ne 0\)时,无解。
点击查看代码
inline int BSGS(int y,int z,int mod){
if(y == 0 && z == 0) return 1;
if(y == 0 && z != 0) return -1;
unordered_map<int,int> mp;
int t = sqrt(mod)+1,now = z%mod;
for(int i = 0;i <= t; ++i){
mp[now] = i;
now = 1ll * now * y % mod;
}
int Ym = power(y,t,mod);now = 1;
for(int i = 1;i <= t; ++i){
now = 1ll * Ym * now % mod;
if(mp.count(now)){
return i*t-mp[now];
}
}
return -1;
}
例题:计算器
第一问快速幂,第二问逆元,注意特判y%p=0时无解,第三问bsgs板子
点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int power(int a,int b,int mod){
int res = 1;
while(b){
if(b&1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return res;
}
inline int BSGS(int y,int z,int mod){
if(y == 0 && z == 0) return 1;
if(y == 0 && z != 0) return -1;
unordered_map<int,int> mp;
int t = sqrt(mod)+1,now = z%mod;
for(int i = 0;i <= t; ++i){
mp[now] = i;
now = 1ll * now * y % mod;
}
int Ym = power(y,t,mod);now = 1;
for(int i = 1;i <= t; ++i){
now = 1ll * Ym * now % mod;
if(mp.count(now)){
return i*t-mp[now];
}
}
return -1;
}
signed main(){
cin.tie(0)->sync_with_stdio(false);
cout.tie(0)->sync_with_stdio(false);
int T,k;
cin>>T>>k;
while(T--){
int y,z,mod;
cin>>y>>z>>mod;
if(k == 1)cout<<power(y,z,mod)<<'\n';
if(k == 2){
if(y%mod == 0) cout<<"Orz, I cannot find x!\n";
else cout<<1ll*z*power(y,mod-2,mod)%mod<<'\n';
}
if(k == 3){
y %= mod;z%=mod;
int ans = BSGS(y,z,mod);
if(ans == -1) cout<<"Orz, I cannot find x!\n";
else cout<<ans<<'\n';
}
}
}
ExBSGS
- 用途:求解\(a^x\equiv b\pmod p\quad (a,b,p\in \mathbb{Z^+})\)
做法:想办法让其变得可以用BSGS求解,那么就是使\(\gcd(a,p) = 1\)。令\(d_1=\gcd(a,p)\),若\(d_1\nmid b\)无解,反之同时除以\(d_1\),得到
\[\frac{a}{d_1}\times a^{x-1}\equiv \frac{b}{d_1}\pmod{\frac{m}{d_1}}
\]
若仍然不互质,重复以上操作,直至\(a\perp \frac{m}{d_1d_2d_3\dotsb d_k}\)
令\(D = \prod_{i-1}^kd_i\),原方程变成了酱紫
\[\frac{a^k}{D}a^{x-1}\equiv \frac{b}{D}\pmod{\frac{m}{D}}
\]
因为\(a\perp \frac{m}{D}\),所以\(\frac{a^k}{D}\perp\frac{m}{D}\),求逆元,扔到等式右边,用bsgs求出\(x-k\)加上k
当解小于k时,提前枚举就好了。
注意\(\frac{m}{D}\)不一定为素数,但\(\gcd(\frac{a^k}{D},\frac{m}{D})=1\),所以逆元要用exgcd求
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
inline int power(int a,int b,int mod){
int res = 1;
while(b){
if(b&1) res = 1ll * res * a % mod;
b >>= 1;
a = 1ll * a * a % mod;
}
return res;
}
int exgcd(int a,int b,int &x,int &y){
if(!b)return x=1,y=0,a;
int res = exgcd(b,a%b,y,x);
y -= a/b*x;
return res;
}
inline int BSGS(int a,int b,int mod){
a %= mod,b %= mod;
if(!a) return (b?-1:1);
__gnu_pbds::gp_hash_table<int,int> mp;
int t = sqrt(mod)+1,res = b;
for(int i = 0;i <= t; ++i){
mp[res] = i;
res = 1ll * a * res % mod;
}
a = power(a,t,mod),res = a;
for(int i = 1;i <= t; ++i){
if(mp[res]){
return i*t-mp[res];
}
res = 1ll * res * a % mod;
}
return -1;
}
inline int ExBSGS(int a,int b,int mod){
a %= mod,b %= mod;
if(b == 1 || mod == 1) return 0;
if(!a) return (b?-1:1);
int tot = 0,gcd = 0,now = 1;
while((gcd = __gcd(a,mod))^1){
if(b%gcd) return -1;
mod /= gcd;b /= gcd;tot++;
now = 1ll * now * (a/gcd) % mod;
if(now == b) return tot;
}
int x,y;
exgcd(now,mod,x,y);
x = (x%mod + mod) % mod;
int ans = BSGS(a,1ll * b * x % mod,mod);
if(ans == -1) return -1;
else return ans + tot;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
int a,p,b;
while(cin>>a>>p>>b&&a&&b&&p){
int ans = ExBSGS(a,b,p);
if(ans == -1) cout<<"No Solution\n";
else cout<<ans<<'\n';
}
}
__________________________________________________________________________________________
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18315293