Description
已知k,a,p,求x ^ k=a (mod p)的所有根(根的范围[0,p-1]
Input
三个整数p,k,a。0 < = a < p < = 10^9, 2 < = k < = 100000
Output
第一行一个整数,表示符合条件的x的个数。
第二行开始每行一个数,表示符合条件的x,按从小到大的顺序输出。
Sample Input
11 3 8
Sample Output
1
2
分析:一道原根的水题。首先,根据原根的性质,每一个1<=x<=phi(n)的数都能用g^i来表示(其中g表示一个原根)。也就是说,原式=x^A=(g^i)^A=(g^A)^i。其中g^A是已知的,也就是一个BSGS的版子了,求出所有i后,g^i就是所有的解,然后排序即可。
代码:
/**************************************************************
Problem: 1420
User: beginend
Language: C++
Result: Accepted
Time:296 ms
Memory:16952 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define LL long long
const int maxn=1500;
const int c=1e6+7;
using namespace std;
LL cnt;
LL p[maxn],ans[maxn];
LL n,a,b,g,k;
struct node{
LL x,y;
}hash[c];
void divide(LL x)
{
for (LL i=2;i<=trunc(sqrt(x));i++)
{
if (x%i==0)
{
p[++cnt]=i;
while (x%i==0) x/=i;
}
}
if (x>1) p[++cnt]=x;
}
LL pow(LL x,LL y)
{
if (y==0) return 1;
if (y==1) return x;
long long d=pow(x,y/2);
d=(d*d)%n;
if (y%2==1) d=(d*x)%n;
return d;
}
void find_root(LL x)
{
LL flag;
for (LL i=1;i<x;i++)
{
flag=0;
for (LL j=1;j<=cnt;j++)
{
if (pow(i,(x-1)/p[j])==1)
{
flag=1;
break;
}
}
if (!flag)
{
g=i;
return;
}
}
}
void find(LL x,LL s)
{
LL t=x%c;
while (hash[t].x!=0)
{
if (hash[t].x==x)
{
if (s-hash[t].y<=n-1) ans[++k]=s-hash[t].y;
}
t=(t+1)%c;
}
}
void insert(LL x,LL y)
{
LL t=x%c;
while (hash[t].x!=0) t=(t+1)%c;
hash[t].x=x;
hash[t].y=y;
}
void BSGS(LL a,LL b)
{
//if (b==1) ans[++k]=0;
LL x=1;
LL block=trunc(sqrt(n))+1;
for (LL i=0;i<block;i++)
{
insert((x*b)%n,i);
x=(x*a)%n;
}
LL y=x,i;
for (LL i=1;i<block;i++)
{
if (i*block>=n) break;
find(y,i*block);
y=(y*x)%n;
}
}
int main()
{
scanf("%lld%lld%lld",&n,&a,&b);
divide(n-1);
find_root(n);
BSGS(pow(g,a),b);
for (LL i=1;i<=k;i++) ans[i]=pow(g,ans[i]);
sort(ans+1,ans+k+1);
printf("%lld\n",k);
for (LL i=1;i<=k;i++) printf("%lld\n",ans[i]);
}