「BZOJ3239」Discrete Logging
Description
Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 2 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that
1 |
B<sup>L</sup> == 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”.
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
1 |
B<sup>(P-1)</sup> == 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
1 |
B<sup>(-m)</sup> == B<sup>(P-1-m)</sup> (mod P) . |
Sample Input
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
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587
题解
裸BSGS,见sdoi计算器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<set> #include<map> #include<vector> #define inf 1000000000 #define ll long long using namespace std; inline int read() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } ll p,y,z; ll qpow(ll a,ll b) { ll tmp=1; a%=p; for(ll i=b;i;i>>=1,a=a*a%p) if(i&1)tmp=tmp*a%p; return tmp; } map<int,int> mp; void solve() { mp.clear(); y%=p; if(y==0&&z==0){puts("1");return;} if(y==0){puts("no solution");return;} int m=ceil(sqrt(p));ll now=1; mp[1]=m+1; for(int i=1;i<m;i++) { now=now*y%p; if(!mp[now])mp[now]=i; } ll ine=1,tmp=qpow(y,p-m-1); for(ll k=0;k<m;k++) { int i=mp[z*ine%p]; if(i) { if(i==m+1)i=0; printf("%lld\n",k*m+i); return; } ine=ine*tmp%p; } puts("no solution"); } int main() { while(scanf("%d%d%d",&p,&y,&z)!=EOF) { solve(); } return 0; } |
大犇您的代码怎么TLE了?