T186383 取模 题解
事实上,这是BSGS的模板题
但是我们注意到$a,b,p$并不保证互质。
所以我们首先需要约分
原方程可化为$a^x+py=b$
等式两边同时除以$g=gcd(a,p)$,得
$a^x/g+py/g=b/g$
于是有$a^x/g \equiv b/g\ (mod\ p/g)$
当b不能被g整除时,$a^x$必然有一个$b$没有的因子$g$,此时原方程无解
当b能够被g整除时,同余恒等式两边可以同时乘以$g$,得$a^x \equiv b\ (mod\ p/g)$
这个时候,$a^x$和$p/g$就一定互质了吗?
然而并不是。例如,当$p=a^5$时,第一次求得的$g=a$,而$p/g=a^4$,此时依然不互质
由此我们需要多次进行求gcd的过程直到$g=1$
之后使用普通的BSGS算法就可以求得解了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#if(__cplusplus == 201103L)
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
namespace std
{
using std::tr1::unordered_map;
using std::tr1::unordered_set;
}
#endif
#include<map>
#include<cmath>
#define int long long
using namespace std;
using namespace tr1;
inline int r()
{
int s=0,k=1;char c=getchar();
while(!isdigit(c))
{
if(c=='-')k=-1;
c=getchar();
}
while(isdigit(c))
{
s=s*10+c-'0';
c=getchar();
}
return s*k;
}
bool wa;
int p,b,n;
int gcd(int a,int b)
{
if(!b)return a;
return gcd(b,a%b);
}
unordered_map<int,int>m;
int pw(int a,int b,int mod)
{
int base=a,ans=1;
while(b)
{
if(b&1)
{
ans*=base;
ans%=mod;
}
base*=base;
base%=mod;
b>>=1;
}
return ans;
}
int x,y;
int exgcd(int a,int b)
{
if(!b)
{
x=1;y=0;
return a;
}
int g=exgcd(b,a%b),tmp=x;
x=y;
y=tmp-y*(a/b);
return g;
}
int ny(int xx,int mod)
{
int g=exgcd(xx,mod);
return (x%mod+mod)%mod;
}
signed main()
{
while(1)
{
bool flag=0;
b=r();p=r();n=r();
if(p==b&&b==n&&n==0)return 0;
m.clear();
while(1)
{
int g=gcd(b,p);
if(n%g)
{
cout<<"No Solution"<<endl;
flag=1;
break;
}
p/=g;
if(g==1)break;
}
if(flag)continue;
//n/=g;
//b%=p;n%=p;
//b/=g;
// cout<<"gcd:"<<g<<"new:"<<b<<" "<<n<<" "<<p<<endl;
int s=sqrt(p)+3;
// cout<<"s:"<<s<<endl;
int now=1;
m[1]=0;
for(int i=1;i<=s;i++)//b^i
{
now*=b;
now%=p;
if(m.find(now)==m.end())m[now]=i;
}
for(int i=0;i<=s;i++)//根号分块 si+j
{
// cout<<"i:"<<i<<endl;
int tmp=pw(b,i*s,p);
// cout<<"原始:"<<tmp<<endl;
tmp=ny(tmp,p);
// cout<<"逆元:"<<tmp<<endl;
int xx=n*tmp;
xx%=p;
// cout<<i<<" "<<xx<<endl;
if(m.find(xx)!=m.end())
{
//if(i==0&&m[xx]==0)continue;
cout<<i*s+m[xx]<<endl;
flag=1;break;
}
//if(i==1)return 0;
}
if(!flag)cout<<"No Solution"<<endl;
}
}
// 547593860 609866328 563487656
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15022893.html