一道ZHX的题 O (1) 快速乘 BSGS

来源:互联网 发布:淘宝客流量过大 编辑:程序博客网 时间:2024/05/21 09:52

大家都很强, 可与之共勉。

【题目描述】
HJA在和学弟学数学,于是便有了一道非常简单的数学题:求满足 的最小自然数x。
【输入格式】
输入数据一行三个正整数a、b、p,我们保证p是一个质数。
【输出格式】
一行一个整数代表最小的自然数x,如果不存在这样的x输出-1。
【样例输入】
2 1 3
【样例输出】
0
【数据范围与规定】
对于30%的数据,1≤p≤1000。
对于100%的数据,1 ≤ a,b < p ≤ 10^12。

题解
就是一个裸的BSGS,可是考完之后才会发现爆long long……

所以恶补了一下O ( 1 ) 的快速乘。

inline long long mmul ( const long long& a, const long long& b )  {    long long lf = a * ( b >> 20 ) % p * ( 1LL << 20 ) % p ;    long long rg = a * ( b & ( ( 1LL << 20 ) - 1 ) ) % p ;    return ( lf + rg ) % p ;}

Code :

# include <cmath># include <cstdio># include <cstring>const long long Base = 100137 ;struct Hash  {    struct edge  {        int nxt ; long long a ; int b ;    } g [Base << 4] ;    int head [Base], ecnt ;    inline void Init ( )  {        ecnt = 0 ;        memset ( head, 0, sizeof head ) ;    }    inline void insert ( long long a, int b )  {        long long key = a % Base ;        for ( register int i = head [key] ; i ; i = g [i].nxt )            if ( g [i].a == a ) return ;        g [++ ecnt] = ( edge ) {  head [key], a, b  } ; head [key] = ecnt ;    }    inline long long query ( long long a )  {        long long key = a % Base ;        for ( register int i = head [key] ; i ; i = g [i].nxt )            if ( g [i].a == a ) return g [i].b ;        return -1 ;    }} hash ;long long a, b, p ;const long long AAA = 1LL << 20, BBB = AAA - 1 ;    long long CCC ;inline long long mmul ( const long long& a, const long long& b )  {    long long lf = a * ( b >> 20 ) % p * CCC ;    long long rg = a * ( b & BBB ) % p ;    return ( lf + rg ) % p ;}inline long long mpow ( register long long a, register long long x, register long long Mod )  {    register long long rt ;    for ( rt = 1 ; x ; x >>= 1, a = mmul ( a, a ) )        if ( x & 1 ) rt = mmul ( rt, a ) ;    return rt ;}inline long long Bsgs ( long long g, long long a, long long p )  {    hash.Init ( ) ;    int b = ( int ) ceil ( sqrt ( a ) ) ;    register long long cur = 1 ;    for ( register int i = 0 ; i < b ; ++ i, cur = mmul ( cur, g ) )  {        if ( cur == a ) return i ;        hash.insert ( cur, i ) ;    }    register long long base = mpow ( cur, p - 2, p ) ;    cur = mmul ( base, a ) ;    for ( register long long i = b ; i < p ; i += b, cur = mmul ( cur, base ) )  {        long long j = hash.query ( cur ) ;        if ( j ^ -1 ) return i + j ;    }    return -1 ;}int main ( ) {    freopen ( "braveheart.in", "r", stdin ) ;    freopen ( "braveheart.out", "w", stdout ) ;    scanf ( "%I64d%I64d%I64d", & a, & b, & p ) ;    CCC = AAA % p ;    return printf ( "%I64d\n", Bsgs ( a, b, p ) ), 0 ;}
原创粉丝点击