HDU 2815 Mod Tree (扩展 Baby Step Giant Step )

Mod Tree

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 96 Accepted Submission(s): 38
 
Problem Description

  The picture indicates a tree, every node has 2 children.
  The depth of the nodes whose color is blue is 3; the depth of the node whose color is pink is 0.
  Now out problem is so easy, give you a tree that every nodes have K children, you are expected to calculate the minimize depth D so that the number of nodes whose depth is D equals to N after mod P.
 
Input
The input consists of several test cases.
Every cases have only three integers indicating K, P, N. (1<=K, P, N<=10^9)
 
Output

            The minimize D.
If you can’t find such D, just output “Orz,I can’t find D!”
 
Sample Input
3 78992 453
4 1314520 65536
5 1234 67
 
Sample Output
Orz,I can’t find D!
8
20
 
Author
AekdyCoin

证明来自:

http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL ;
const int N = 100010;

struct B
{
    LL num , id ;
    bool operator < ( const B &a ) const{
        if( num != a.num ) return num < a.num;
        else return id < a.id ;
    }
}baby[N];

LL n , k , p ;
int tot ;
void e_gcd( LL &x , LL &y , LL &d , LL a , LL b ){
    if( b == 0 ){ x = 1 , y = 0 ; d = a ; return ; }
    e_gcd( y , x , d , b , a%b );
    y -= x* (a/b) ;
}

int inv( LL a, LL b ,LL n )
{
    LL d,e,x,y ;
    e_gcd(x,y,d,a,n);
    e = ( x * b ) % n ;
    return e < 0 ? e + n : e;
}

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

LL quick_mod( LL a , LL b ,LL mod )
{
    LL res =1 ;
    while( b )
    {
        if( b &1 ) res = res * a % mod ;
        a = a * a % mod ;
        b >>= 1 ;
    }
    return res ;
}

int find( LL n )
{
    int l = 0 , r = tot - 1 ;
    while( l <= r ){
        int m = (l + r) >> 1;
        if( baby[m].num == n){
            return baby[m].id;
        }
        else if( baby[m].num < n )
            l = m + 1;
        else
            r = m - 1 ;
    }
    return -1;
}



void run()
{
    if( p <= n ){
         puts("Orz,I can’t find D!");
         return ;
    }
    LL temp = 1 % p ;
    for( int i = 0  ; i < 100 ; ++i ) {
        if( temp == n ){
                printf("%d
",i);
                return ;
        }
        temp = temp * k % p ;
    }

    LL d = 0 , kk = 1 % p ;
    while( ( temp = gcd( k , p ) ) != 1 ){
        if( n % temp ) {
             puts("Orz,I can’t find D!");
             return ;
        }
        d ++ ;
        p /= temp;
        n /= temp;
        kk =  k / temp * kk % p ;
    }
    int m = ( int ) ceil( sqrt( (double)p ) );
    baby[0].num = 1 , baby[0].id = 0 ;
    for( int i = 1 ; i <= m ; ++i ){
        baby[i].num = baby[i-1].num * k % p ;
        baby[i].id = i ;
    }
    sort( baby , baby + m + 1 ) ;
    tot = 1 ;
    for( int i = 1 ; i <= m ; ++i ){
        if(baby[i].num != baby[tot-1].num ){
            baby[tot++] = baby[i];
        }
    }

    LL am = quick_mod( k , m , p );

    for( int j = 0 ; j <= m ; ++j ){
        temp = inv(kk,n,p);
        if( temp < 0 ){
            continue ;
        }
        int pos = find( temp );
        if( pos != -1 ){
            printf("%d
", m * j + d + pos );
            return ;
        }
        kk = kk * am % p    ;
    }
     puts("Orz,I can’t find D!");
}
int main()
{
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
    while( scanf("%I64d%I64d%I64d",&k,&p,&n) != EOF ) run();
}
only strive for your goal , can you make your dream come true ?
原文地址:https://www.cnblogs.com/hlmark/p/4009483.html