题目描述
Given a prime P,2<=P<231P, 2 <= P < 2^{31}P,2<=P<231, an integer B,2<=B<PB, 2 <= B < PB,2<=B<P, and an integer N,1<=N<PN, 1 <= N < PN,1<=N<P, compute the discrete logarithm of NNN, base BBB, modulo PPP. That is, find an integer LLL such that
BL==N(modP)B^L == N (mod P)BL==N(modP)输入格式
Read several lines of input, each containing P,B,NP,B,NP,B,N separated by a space,
输出格式
For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".
样例
样例输入
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
样例输出
0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587
数据范围与提示
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(modP)for any prime PPP 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)(modP)背景
这题的英文题面是真的没有翻译!!!!
差评。
看懂题面简直费死劲了。
结果还是导致了理解偏差QAQ,发此博客献给我的英语老师 Mr.jia
思路分析
? 你们知道北上广深嘛?
指 BSGS算法 ,我今日的研究成果。
其实如果知道这个算法,那么这道题就只是个代码实现了。【确认过,是板子
那么我来具体介绍一下这个算法。
BSGS
明确:BSGS用于求解高次同余方程的整数解。
上面就是一个高次同余方程。
我们来思考一下,有没有什么定理啊,推论啊能够化简这个式子。
· 在求解这个问题之前,我们先假设A与C互质。【A和C不互质的情况,先进行消因子处理成互质的。
然后,根据费马小定理可以得到 :
当A和C互质的时候,有如下:
所以循环节的长度不会大于c,即数据小的时候,可以枚举 0≤x≤c-1
那么,数据大了怎么办呢?
这就要用到BSGS了。
具体就是代码实现了。
代码实现
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<map> #define ll long long #define rint register int using namespace std; ll p,b,n; map<ll,int> hash; ll fpow(ll x,ll b) { ll res=1; while(b) { if(b&1) { res*=x; res%=p; } b>>=1; x*=x; x%=p; } return res; } int main() { while(scanf("%lld%lld%lld",&p,&b,&n)!=EOF) { if(!(b%p)) { cout<<"no solution"<<endl; continue; } hash.clear(); ll m=ceil(sqrt(p)); ll ans=0; for(rint i=0;i<=m;i++) { if(!i) { ans=n%p; hash[ans]=i; continue; } ans=ans*b%p; hash[ans]=i; } ans=1; bool flag=false; for(rint i=1;i<=m;i++) { ans=(ans*fpow(b,m))%p; if(hash[ans]) { ans=i*m-hash[ans]; ans=(ans%p+p)%p; printf("%lld ",ans); flag=true; break; } } if(!flag) cout<<"no solution"<<endl; } return 0; }