Discrete Logging
Time Limit: 5000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u
Description
Given a prime P, 2 <= P < 2 31, 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 thatBL == 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 1111111111Sample Output
0 1 3 2 0 3 1 2 0 no solution no solution 1 9584351 462803587Hint
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
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) .
/*
跟上一题一样
题意:XY mod Z = K,给出x,z,k求y。(0 ≤ X, Z, K ≤ 109)其中Y (0 ≤ Y < Z).假如找不到合适的答案,请输出“No Solution”。 求解:mod z产生的集合最多有z个元素,这构成一个群。 分析:其时这个方法我还没搞明白,是从网上搞到的,这个模版还是比较稳当的 代码:*/
#include <iostream> #include <string.h> #include <math.h> using namespace std; const long long mod=800000; const long long MAX=800000; struct data { long long m,n,next; }ln[MAX]; long long st[MAX],s; void insert(long long m,long long n) { long long mm = m%mod; long long pos = st[mm]; while(pos != -1 && ln[pos].m != m) pos = ln[pos].next; if(pos == -1) { ln[s].m = m; ln[s].n = n; ln[s].next = st[mm]; st[mm] = s++; } else ln[pos].n = n; } long long find(long long m) { long long mm=m%mod; long long pos=st[mm]; while(pos!=-1) { if(ln[pos].m==m) return ln[pos].n; pos=ln[pos].next; } return -1; } long long MOD(long long b,long long n,long long mod) { long long t=1; while(n) { if(n & ((__int64)1)) t = (t*b)%mod; b = (b*b)%mod; n >>= ((__int64)1); } return t%mod; } long long solve(long long X,long long Z,long long K)//用来求X^Y mod Z = k 中的Y { long long m,i,j,b; X %= Z; K %= Z; s = 0; memset(st, -1, sizeof(st)); m = (int)sqrt((double)Z); long long t = K; for(i=0; i <= m; i++) { insert(t, i); t *= X; t %= Z; } b = MOD(X, m, Z); t = 1; long long ans = -1; for(i=1; i <= m; i++) { t *= b; t %= Z; long long x = find(t); if(x != -1) { ans = i*m-x; break; } } if(ans != -1 && MOD(X, ans, Z) == K) return ans; else return -1; } int main() { long long Z,X,K; long long power; while(cin>>Z>>X>>K) { if(!X && !Z && !K)cout<<0<<endl; power=solve(X,Z,K); if(power!=-1)cout<<power<<endl; else printf("no solution\n"); } return 0; }