POJ 2417/BZOJ 3239(Discrete Logging-BSGS)[Template:数论]


Discrete Logging

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 4236   Accepted: 1948

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

b^L=b^k1*b^k2

已知b^k1 hash b^k2 复杂度O(sqrt(F)*hash(F))  hash(F)为哈希的复杂度

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (1000000)
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
char s[]="no solution\n";

class Math
{
public:
	ll gcd(ll a,ll b){if (!b) return a;return gcd(b,a%b);}
	ll abs(ll x){if (x>=0) return x;return -x;}
	ll exgcd(ll a,ll b,ll &x, ll &y)
	{
	    if (!b) {x=1,y=0;return a;}
	    ll g=exgcd(b,a%b,x,y);
	    ll t=x;x=y;y=t-a/b*y;
	    return g;
	}
	ll pow2(ll a,int b,ll p)
	{
	    if (b==0) return 1;
	    if (b==1) return a;
	    ll c=pow2(a,b/2,p);
	    c=c*c%p;
	    if (b&1) c=c*a%p;
	    return c;
	}
	ll Modp(ll a,ll b,ll p)
	{
	    ll x,y;
	    ll g=exgcd(a,p,x,y),d;
	    if (b%g) {return -1;}
	    d=b/g;x*=d,y*=d;
	    x=(x+abs(x)/p*p+p)%p;
	    return x;
	}
	int h[MAXN];
	ll hnum[MAXN];
	int hash(ll x)
	{
	    int i=x%MAXN;
	    while (h[i]&&hnum[i]!=x) i=(i+1)%MAXN;
	    hnum[i]=x;
	    return i;
	}
	ll babystep(ll a,ll b,int p)
	{
		MEM(h) MEM(hnum)
		int m=sqrt(p);while (m*m<p) m++;
	    ll res=b,ans=-1;  

	    ll uni=pow2(a,m,p);
	    if (!uni) if (!b) ans=1;else ans=-1; //特判
	    else
	    {  

	        Rep(i,m+1)
	        {
	            int t=hash(res);
	            h[t]=i+1;
	            res=(res*a)%p;
	        }
	        res=uni;  

			For(i,m+1)
			{
	            int t=hash(res);
	            if (h[t]) {ans=i*m-(h[t]-1);break;}else hnum[t]=0;
	            res=res*uni%p;
	        }  

		}
		return ans;
	}
}S;

int main()
{
//	freopen("poj2471.in","r",stdin);
//	freopen(".out","w",stdout);

	ll p,b,n;
	while(cin>>p>>b>>n)
	{
		ll ans=S.babystep(b,n,p);
		if (ans==-1) cout<<s;
		else cout<<ans<<endl;
	}

	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-14 04:25:09

POJ 2417/BZOJ 3239(Discrete Logging-BSGS)[Template:数论]的相关文章

BZOJ 3239 Discrete Logging(BSGS)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3239 [题目大意] 计算满足 Y^x ≡ Z ( mod P) 的最小非负整数 [题解] BSGS裸题. [代码] #include <cstdio> #include <cmath> #include <map> #include <algorithm> #include <tr1/unordered_map> using name

bzoj 3239: Discrete Logging【BSGS】

BSGS的板子题 此时 \( 0 \leq x \leq p-1 \) 设 \( m=\left \lceil \sqrt{p} \right \rceil ,x=i*m-j \)这里-的作用是避免逆元 于是可以把式子变形成这样:\( a^{im}\equiv ba^j(mod p) \) 枚举右边\( 0 \leq j <m \) ,用map或者hash以模数为下标来存每一个j 枚举左边\( 0 \leq i <m \) ,在map或者hash中查找对应的模数 #include<ios

BZOJ 3239 Discrete Logging Baby-Step-Giant-Step

题目大意:给定P,B,N,求最小的L使B^L≡N (mod P) (P是质数) 裸的BSGS... 练练手吧- - #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 100100 #define INF 0x3f3f3f3f using namespace std; typedef pai

POJ 2417 Discrete Logging BSGS

Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4011   Accepted: 1849 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, b

【BZOJ】3239: Discrete Logging

http://www.lydsy.com/JudgeOnline/problem.php?id=3239 题意:原题很清楚了= = #include <bits/stdc++.h> using namespace std; map<int, int> s; typedef long long ll; int mpow(int a, int b, int p) { a%=p; int r=1; while(b) { if(b&1) r=((ll)r*a)%p; a=((ll)

Discrete Logging POJ - 2417(BSGS)

Discrete Logging POJ - 2417 题意:给P,B,N,求最小的L使得 BL≡N (mod P) Baby Step Giant Step 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 const int maxn=76543;

BSGS算法+逆元 POJ 2417 Discrete Logging

POJ 2417 Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4860   Accepted: 2211 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarith

[poj 2417]Discrete Logging 数论 BSGS

Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3516   Accepted: 1651 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.

poj 2417 Discrete Logging(A^x=B(mod c),普通baby_step)

http://poj.org/problem?id=2417 A^x = B(mod C),已知A,B,C,求x. 这里C是素数,可以用普通的baby_step. 在寻找最小的x的过程中,将x设为i*M+j.从而原始变为A^M^i * A^j = B(mod C),D = A^M,那么D^i * A^j = B(mod C ), 预先将A^j存入hash表中,然后枚举i(0~M-1),根据扩展欧几里得求出A^j,再去hash表中查找相应的j,那么x = i*M+j. 确定x是否有解,就是在循环i