voidbsgs()// 预处理 { for (LL i = 0,x=1; i<=k; i++) { t[r=x%P] = i; x = x*g %P; } // 最后 r就是 g^k mod P的余数 t[1,...,g^k mod P的余数] = i for (LL i = 1, y = r; i<=k; i++) { s[y%P] = i; y = y*r %P; } // 最后 s[r,...,r^k mod P 的余数] = i, 即 s[g^k,...,g^(k^2) mod P 的余数] = i; }
LL qsm(LL B, LL a)// 求B^a mod P 的快速幂(不用快速幂必然吃T) 这里用的是快速幂的标准板子 { LL ans = 1; while(a) { if (a&1) // B是奇数 { ans = ans * B %P; } if (a>1) { B = B*B %P; } a = a >>1; } return ans; }
LL decypher(LL A, LL B)// g^a≡A(mod P) ,如果 a=k*i-j的话,则g^(ki)≡A*g^j(mod P),而缓存g^(ki)和 g^j mod P 的余数就是预处理方法bsgs()干的事情. 这里只需要乘以A进行验证就行了 { mit it = t.begin(); while(it!=t.end()) { LL tmp = A*it->first%P; // A*g^j模掉P的余数 if (s.count(tmp)) { return qsm(B, s[tmp]*k-it->second); // 则返回 a=k*i-j } it++; } }