Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 6190 | Accepted: 2746 |
Description
Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that
B
L
== N (mod P)
Input
Read several lines of input, each containing P,B,N separated by a space.
Output
For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".
Sample Input
5 2 1
5 2 2
5 2 3
5 2 4
5 3 1
5 3 2
5 3 3
5 3 4
5 4 1
5 4 2
5 4 3
5 4 4
12345701 2 1111111
1111111121 65537 1111111111
Sample Output
0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587
Hint
The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states
for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m
B
(P-1)
== 1 (mod P)
for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m
B
(-m)
== B
(P-1-m)
(mod P) .
Source
BSGS模板
#include <cstdio> #include <cmath> #include <map> using namespace std; map<long long,int>q; int P,B,N; long long ans; bool flag=false; long long ksm(int m,int n,int ha) { long long r=1,base=m; for(;n;n>>=1) { if(n&1) r=(r*base)%ha; base=(base*base)%ha; } return r; } void bsgs(long long y,long long z,long long p) { q.clear(); int m=(int)ceil(sqrt((double)p));//防止编译错误 flag=false; q[1]=m+1; long long a=1; for(int i=1;i<m;i++) { a=a*y%p; if(!q[a]) q[a]=i; } long long inv=1; a=ksm(y,p-m-1,p); for(int k=0;k<m;k++) { long long an=z*inv%p; if(q[an]) { int v=q[an]; if(v==m+1) {ans=k*m;flag=true;return;} else {ans=k*m+v;flag=true;return ;} } inv=inv*a%p; } } int main() { for(;scanf("%d%d%d",&P,&B,&N)!=EOF;) { if(B%P==0&&N==0) printf("1 "); else if(B%P==0) printf("no solution "); else { bsgs(B,N,P); if(!flag) printf("no solution "); else printf("%lld ",ans); } } return 0; }