称之为伪高精,是因为这用较低常数稍微扩充了的变量范围。它的范围仍然有限,只不过做到了 long long
差一点点就能做到的事,如 BZOJ 2854。
Luogu P11144 交互题,每次询问给定整数
$x\in[0, 10^{17}]$ ;$m\in[1,4\times 10^8]$。多组数据,每个测试点不超过 100 组。
一道很适合引入中国剩余定理(CRT)的题目。这篇题解面向熟悉快速幂思想,将要学习 CRT 的读者。
联想天干地支纪年法:用年份模 10 和 12 的结果来表示年份模 60 的结果。
取两个大质数,设为
“比较简单地合并”能有多简单?我们想设 $$ x \equiv w_1m_1+w_2m_2 \pmod {PQ} $$
-
$w_1$ 是$Q$ 的倍数,而且除以$P$ 的余数是 1。 -
$w_2$ 是$P$ 的倍数,而且除以$Q$ 的余数是 1。
可以验证这样的形式符合上面的方程组,实际上这是 CRT 的特殊形式。由于已经要求
这是寻找
using ll = long long; // 后面省略这行
void prime() {
for (ll i = 1e17; i; i--)
if ([](int i) -> bool {
for (int j = 2; j * j <= i; j++)
if (i % j == 0) return false;
return true;
}(i)) {
std::cout << i << '\n';
break;
}
}
然后我找到了
这是寻找
void weight() {
for (ll i = 1; i < P; i++)
if (i * Q % P == 1) {
std::cout << i << '\n';
break;
}
}
我找到了
接着是合并。因为相乘的两个数
const ll M = P * Q;
ll multiply(ll x, ll y) {
ll a = 0;
while (y) {
if (y & 1) a = (a + x) % M;
x = x * 2 % M, y >>= 1;
}
return a;
}
#include <iostream>
using ll = long long;
const ll w1 = 143999966840001887ll,
w2 = 15999996360000205ll,
M = 159999963200002091ll;
ll f(ll x, ll y) {
ll a = 0;
while (y) {
if (y & 1) a = (a + x) % M;
x = x * 2 % M, y >>= 1;
}
return a;
}
int main() {
int t; std::cin >> t; while (t--) {
ll m1, m2;
std::cout << "? 399999959" << std::endl;
std::cin >> m1;
std::cout << "? 399999949" << std::endl;
std::cin >> m2;
std::cout << "! " << (f(w1, m1) + f(w2, m2)) % M << std::endl;
}
}