0
点赞
收藏
分享

微信扫一扫

poj2417 Discrete Logging

左小米z 2022-08-08 阅读 20


​​http://www.elijahqi.win/archives/3005​​​
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
BL == 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
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
Waterloo Local 2002.01.26
BSGS模板题
求一个最小的x使其成立ax≡b(modp) a x ≡ b ( m o d p )
根据欧拉定理aφ(p)≡1(modp) a φ ( p ) ≡ 1 ( m o d p )
所以在p是质数的情况下我的这个余数一共只有0~p-2那么多 再之后就循环了 因为我们要找出最小的所以当然不能让其循环了 考虑原先暴力的做法是一个一个枚举x 这时我们设定x=i×m+j x = i × m + j 设m=⌈mod−−−−√⌉ ⌈ m o d ⌉
那么可知i=0~m,j=0~m-1
那么原式可以写成ai∗m≡b∗a−j a i ∗ m ≡ b ∗ a − j

#include<cstdio>
#include<vector>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#define ll long long
#define pa pair<int,int>
#include<algorithm>
using namespace std;
const int N=1e5;
inline char gc(){
static char now[1<<16],*S,*T;
if(T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline bool read(int &x){
x=0;int f=1;char ch=gc();if (ch==EOF) return 0;
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();x=x*f;
return 1;
}
namespace ht{
const int mod=1e6+7;int tmp,cnt;bool flag[mod];vector<pa>hs[mod];
inline void init(){memset(flag,0,sizeof(flag));}
inline void insert1(int x,int id){tmp=x%mod;
if (!flag[tmp]) hs[tmp].clear(),flag[tmp]=1;
for (int i=0;i<hs[tmp].size();++i) if (hs[tmp][i].first==x) return;
hs[tmp].emplace_back(make_pair(x,id));
}
inline int query(int x){tmp=x%mod;
if (!flag[tmp]) hs[tmp].clear(),flag[tmp]=1;
for (int i=0;i<hs[tmp].size();++i){
if (hs[tmp][i].first==x) return hs[tmp][i].second;
}return -1;
}
}
int mod,b,a;
inline int ksm(ll b,int t){
int tmp=1;for (;t;t>>=1,(b*=b)%=mod) if (t&1) tmp=b*tmp%mod;return tmp;
}
int main(){
freopen("poj2417.in","r",stdin);
while(read(mod)&&read(a)&&read(b)){static int inva,tmp1,ans;static ll tmp,tmp2;
ht::init();int m=ceil(sqrt(mod));tmp=b,inva=ksm(a,mod-2);
for (int i=0;i<m;++i)
ht::insert1(tmp,i),(tmp*=inva)%=mod;
ans=-1;tmp=ksm(a,m);tmp2=1;
for (int i=0;i<=m;++i) {
tmp1=ht::query(tmp2);
if (tmp1!=-1) {ans=i*m+tmp1;break;}(tmp2*=tmp)%=mod;
}if (ans==-1) puts("no solution");else printf("%d\n",ans);
}
return 0;
}


举报

相关推荐

0 条评论