离散对数二连 poj 2417 Discrete Logging & HDU 2815 Mod Tree

题目就不贴了。都是一样的套路求解a^x % c = b的最小x

注意HDU的题目很坑,有b比c大和题目中输出信息为全角引号的坑

下面贴的是HDU的版本,poj的改一下a,b,c顺序和输出就好

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
#define MOD 99991
#define N 100005
struct Hash{
    bool f;
    LL Key;
    LL Value;
};
LL a,b,c;
Hash hashs[N];
void Init(){
    for (int i=0;i<N;i++){
        hashs[i].f = 0;
        hashs[i].Key = -1;
        hashs[i].Value = -1;
    }
}
void Insert(LL Key,LL Value){
    LL t = Value % MOD;
    while (hashs[t].f && hashs[t].Value != Value){
        t ++; t %= MOD;
    }
    if (!hashs[t].f){
        hashs[t].f = 1; hashs[t].Key = Key;
        hashs[t].Value = Value;
    }
}
LL Find(LL Value){
    LL t = Value % MOD;
    while (hashs[t].f && hashs[t].Value != Value){
        t ++; t %= MOD;
    }
    if (!hashs[t].f) return -1;
    return hashs[t].Key;
}
LL gcd(LL a, LL b){
    if (b == 0) return a;
    return gcd(b,a % b);
}
void Extended_Euclid(LL a,LL b,LL &x,LL &y){
    if (b == 0){
        x = 1; y = 0; return;
    }
    Extended_Euclid(b,a%b,x,y);
    LL tmp = x;
    x = y;
    y = tmp - (a / b) * y;
}
LL Baby_Step(LL a,LL b,LL c){
    LL ret = 1;
    for (int i=0;i<=50;i++){
        if (ret == b) return i;
        // cout << ret << endl;
        ret = ret * a % c;
    }
    // cout << "HERE";
    LL ans = 1,tmp,cnt = 0;
    while ((tmp = gcd(a,c)) != 1){
        if (b % tmp) return -1;
        b /= tmp;
        c /= tmp;
        ans = ans * (a/tmp) % c;
        cnt ++;
    }
    LL M = ceil(sqrt(1.0*c));
    LL t = 1;
    for (int i=0;i<=M-1;i++){
        Insert(i,t);
        t = t * a % c;
    }
    for (int i=0;i<=M-1;i++){
        LL x,y;
        Extended_Euclid(ans,c,x,y);
        LL Value = x * b % c;
         Value = (Value + c) % c;
        LL Key = Find(Value);
        if (Key != -1) return i * M + Key + cnt;
        ans = ans * t % c;
    }
    return -1;
}
int main()
{
    // freopen("test.in","r",stdin);
    // 该程序可求解a^x == b (mod c),注意输入时数据a,b,c的顺序
    while (cin >> a >> c >> b){
        Init();
        if (b >= c){
           cout << "Orz,I can’t find D!" << endl;
           continue;
        }
        if (a == 0 && b == 0 && c == 0) break;
        a %= c; b %= c; // in case a > c or b > c
        LL ans = Baby_Step(a,b,c);
        if (ans == -1){
            cout << "Orz,I can’t find D!" << endl;
        }
        else
            cout << ans << endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ToTOrz/p/7404021.html