本题在数论上面的考察不亚于SDOI2017树点涂色一题在树论上的考察
Description
求满足 (x^kequiv a (mod p)) 的所有的 (x)
且 (xin[0,p-1])
保证 (p) 为质数
Solution
先把 (a=0) 的判掉
我们发现一般的 (bsgs) 可以求指数,但是不能求底数
那么我们转化一发:
原根科技!!!
求原根啥的 (51nod) 上面有题做
我们发现 (p) 是个素数,就会有原根
原根的求法
如果是个质数,那么就找到 (p-1) 所有的质因子,
然后上判断当前的值 (x) 是不是可以满足对于所有的 (d_i) 不存在 (x^{frac {p-1} {d_i}} equiv 1 (mod p))
求完原根之后,我们就可以把右边表示成
[g^{id_a}
]
左边也就成了:
[(g^{id_x})^k
]
所以推推式子:
这个(id_x imes kequiv id_a (mod varphi(p)))
理解:指数上有欧拉定理……
(id_a) 是可以 (bsgs) 求的,(k) 是个给的
然后就上 (exgcd) 把 (id_x) 的解和通解求一求
最后输出就 (OK)
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
inline int ksm(int x,int y,int p)
{
int res=1; for(;y;y>>=1,(x*=x)%=p) if(y&1) (res*=x)%=p;
return res;
}
inline void exgcd(int a,int b,int &x,int &y)
{
if(!b) return x=1,y=0,void();
exgcd(b,a%b,x,y); int t=x; x=y;
y=t-(a/b)*y;
return ;
}
const int N=2e5+10;
int d[N],cnt,p,k,a;
inline bool check(int x)
{
for(int i=1;i<=cnt;++i) if(ksm(x,(p-1)/d[i],p)==1) return 0;
return 1;
}
inline int find(int p)
{
int t=p-1;
for(int i=2;i*i<=t;++i)
{
if(t%i!=0) continue;
d[++cnt]=i; while(t%i==0) t/=i;
} if(t!=1) d[++cnt]=t;
int g=1; while(g<p) if(check(g)) return g; else g++;
return -1;
}
map<int,int> mp;
inline int bsgs(int y,int z,int p)
{
int s=ceil(sqrt(p)),t=z%p; mp[t]=0;
for(int i=1;i<=s;++i) (t*=y)%=p,mp[t]=i;
int base=ksm(y,s,p),now=1;
for(int i=1;i<=s;++i)
{
(now*=base)%=p;
if(!mp.count(now)) continue;
int t=i*s-mp[now];
return (t%p+p)%p;
}
}
int num,out[N];
signed main()
{
p=read(); k=read(); a=read();
if(!a) return puts("1
0"),0;
int g=find(p),ans=bsgs(g,a,p);
int gcd=__gcd(k,p-1);
if(ans%gcd) return puts("0"),0;
int A=k/gcd,B=(p-1)/gcd,x,y;
exgcd(A,B,x,y);
(x+=B)%=B; x=(x*(ans/gcd)+B)%B;
while(x<p-1)
{
out[++num]=ksm(g,x,p);
x+=B;
} sort(out+1,out+num+1);
printf("%lld
",num);
for(int i=1;i<=num;++i) printf("%lld
",out[i]);
return 0;
}
}
signed main(){return yspm::main();}
Review
如果出现了底数不好求的情况
我们用原根把底数的计算转到质数上再进行其他操作