Discrete Logging


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<iomanip>

using namespace std;

//模板,A ^ B % C = K ,求 B 
#define maxn 65535
struct hash
{
	int a , b , next ;
}Hash[ maxn * 2 ] ;

int flg[ maxn + 66 ];
int top , idx ; 
void ins( int a , int b )
{
	int k = b & maxn ;
	if( flg[ k ] != idx )
	{
		flg[ k ] = idx ;
		Hash[ k ].next = -1 ;
		Hash[ k ].a = a ;
		Hash[ k ].b = b ;
		return ;
	}
	while( Hash[ k ].next != -1 )
	{
		if( Hash[ k ].b == b )
			return ;
		k = Hash[ k ].next ;
	}
	Hash[ k ].next = ++top ;
	Hash[ top ].next = -1  ;
	Hash[ top ].a = a ;
	Hash[ top ].b = b ; 
}

int find( int b )
{
	int k = b & maxn ;
	if( flg[ k ] != idx )
		return -1 ;
	while( k != -1 )
	{
		if( Hash[ k ].b == b )
			return Hash[ k ].a ;
		k = Hash[ k ].next ;
	}
	return -1 ;
}

int gcd( int a , int b )
{
	return b == 0 ? a : gcd( b , a % b ) ;
}

int ex_gcd( int a , int b , int &x , int &y )
{
	if( b == 0 )
	{
		x = 1 ;
		y = 0 ;
		return a ;
	}
	int ret = ex_gcd( b , a % b , x , y ) ;
	int t = x ;
	x = y ;
	y = t - ( a / b ) * y ;
	return ret ;
}

int Inval( int a , int b , int n )
{
	int x , y , e ;
	ex_gcd( a , n , x , y ) ;
	e = ( long long ) x * b % n ;
	return e < 0 ? e + n : e ;
}

int pow_mod( long long a , int b , int c )
{
	long long ret = 1 % c ;
	a %= c ;
	while( b )
	{
		if( b & 1)
			ret = ret * a % c ;
		a = a * a % c ;
		b >>= 1 ;
	}
	return ret ;
}

int BabyStep( int A , int B , int C )
{
	top = maxn ; 
	++idx ;
	long long buf = 1 % C , D = buf , K ;
	int i , d = 0 , tmp ;
	for( i = 0 ; i <= 100 ; buf = buf * A % C , ++i )
		if( buf == B )
			return i ;
	while( ( tmp = gcd( A , C ) ) != 1 )
	{
		if( B % tmp )
			return -1 ;
		++d ;
		C /= tmp ;
		B /= tmp ;
		D = D * A / tmp % C ;
	}
	int M = ( int )ceil( sqrt( ( double ) C ) ) ;
	for( buf = 1 % C , i = 0 ; i <= M ; buf = buf * A % C , ++i )
		ins( i , buf ) ;
	for( i = 0 , K = pow_mod( ( long long )A , M , C ) ; i <= M ; D = D * K % C , ++i )
	{
		tmp = Inval( ( int ) D , B , C ) ;
		int w ;
		if( tmp >= 0 && ( w = find( tmp ) ) != -1 )
			return i * M + w + d ;
	}
	return -1 ;
}

//模板,A ^ B % C = K ,求 B 

int main()
{
	int A , B , C ;
	while( scanf( "%d%d%d" , &C , &A , &B ) != EOF )
	{
		B %= C ;
		int tmp = BabyStep( A , B , C ) ;
		if( tmp < 0 )
			printf( "no solution\n" ) ; 
		else
			printf( "%d\n" , tmp ) ;
	}
	return 0 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值