题意:模方程
题目没说。但是此题里p应该为素数。。
1.原根的概念。
对于素数p,如果存在一个正整数
根据欧拉定理可知,
2.原根的求法。
p的原根有
枚举那些
3.模方程求解。
如果找到了p的一个原根m,设
依然有很多细节:
1、1和2没有原根,特判。
2、b=0特判。因为没有解。
//x^a = b (mod p)
//1,2 没有原根,特判。
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
#define ll long long
using namespace std;
ll p;
int cnt;
ll pr[1000005];
ll pow(ll a,ll b,ll p){
ll ret=1;
while(b){
if(b&1) ret=ret*a%p;
a=a*a%p;b>>=1;
}
return ret;
}
ll inv(ll a,ll p){return pow(a,p-2,p);}
void getprime(ll now){
for(int i=2;i*i<=now;i++)
if(now%i==0){
pr[++cnt]=i;
while(now%i==0) now/=i;
}
if(now!=1) pr[++cnt]=now;
//for(int i=1;i<=cnt;i++) printf("%lld ",pr[i]);puts("");
}
bool judge(ll x){
for(int i=1;i<=cnt;i++)
if(pow(x,(p-1)/pr[i],p)==1) return 0;
return 1;
}//若a为循环节,ka也为循环节
ll getgen(){
for(ll i=2;;i++)
if(judge(i)) return i;
}
map<ll,ll>hash;
ll BSGS(ll a,ll b,ll p){
hash.clear();
int m=(int)sqrt(p)+1;
ll e=1;hash[e]=0;
ll v=inv(pow(a,m,p),p);
for(int i=1;i<m;i++){
e=e*a%p;
if(!hash.count(e)) hash[e]=i;
}
for(int i=0;i<=m;i++){
if(hash.count(b)) return i*m+hash[b];
b=b*v%p;
}
return -1;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b) {x=1;y=0;d=a;return;}
exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
map<ll,bool>vis;
ll ans[1000005];
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
ll a,b,m,counter=0;
scanf("%lld%lld%lld",&p,&a,&b);b%=p;
if(b==0) return puts("1\n0"),0;
if(p==2) {
if(b==1) puts("1\n1");
else puts("1\n0");
return 0;
}
if(p==3){
for(int i=0;i<=2;i++)
if(pow(i,a,p)==b) counter++;
printf("%lld\n",counter);
for(int i=0;i<=2;i++)
if(pow(i,a,p)==b) printf("%d\n",i);
return 0;
}
getprime(p-1);
m=getgen();
ll z=BSGS(m,b,p);
ll d,x,y;
exgcd(a,p-1,d,x,y);
if(z%d!=0) return puts("0"),0;
ll t=(p-1)/d;
x=x*(z/d)%t;x=(x%t+t)%t;
for(ll tt=pow(m,x,p);!vis.count(tt);x+=t,tt=pow(m,x,p)) vis[tt]=1,ans[++counter]=tt;
printf("%lld\n",counter);
sort(ans+1,ans+1+counter);
for(int i=1;i<=counter;i++) printf("%lld\n",ans[i]);
return 0;
}