ll exgcd(ll a, ll b, ll &x, ll &y){ if (!b) { x = 1, y = 0; return a; } ll d = exgcd(b, a % b, y, x); y -= a / b * x; return d; }
ll inv(ll x, ll p){ ll ans, tmp; exgcd(x, p, ans, tmp); return (ans % p + p) % p; }
ll CRT(){ ll res = 0; for (int i = 1; i <= n; i++) M *= m[i]; for (int i = 1; i <= n; i++) { ll Mi = M / m[i]; res += a[i] * Mi * inv(Mi, m[i]); } return res % M; }
ll exgcd(ll a, ll b, ll &x, ll &y){ // 扩展欧几里得过程,求解特解 t1 和 t2 if (!b) { x = 1, y = 0; return a; } ll d = exgcd(b, a % b, y, x); y -= a / b * x; return d; }
ll mul(ll a, ll b, ll p){ // 著名的龟速乘,就是把快速幂中的乘号改成加号,用来在不爆范围的情况下计算乘积取模的结果 ll res = 0; bool flag = (b < 0) ^ (a < 0); // 处理负数情况,同号相乘为正,异号为负 a = abs(a) % p; b = abs(b) % p; // 注意到:a * (-b) = -(a * b),数字按绝对值相乘,负号最后处理 while (b) { if (b & 1) res = (res + a) % p; a = (a + a) % p; b >>= 1; } return res * (flag ? -1 : 1) % p; // 处理负号 }
ll exCRT(){ while (stk.size() > 1) { // 不断合并方程直至剩下最后一个 Equation cur = stk.top(); stk.pop(); Equation nxt = stk.top(); stk.pop();