// 求解ax+my=b的x,即ax==b(mod m),答案存在ans[0...d-1]中,返回值d为答案个数 intmod_equation(int a, int b, int m) { exgcd(a, m, d, x, y); if (b % d) // 无解 return-1; x = x * (b / d) % m; for (int i = 0; i < d; i++) ans[i] = (x + i * m / d) % m; return d; }
// 中国剩余定理解一元线性同余方程组,数组从0标号 ll CRT(int a[], int m[], int n) { ll M = 1ll, ans = 0, tmp; for (int i = 0; i < n; i++) M *= m[i]; for (int i = 0; i < n; i++) { tmp = M / m[i]; ans = (ans + a[i] * tmp % M * inv(tmp) % M) % M; } return ans; }
// 求解a1x1+a2x2+...+anxn==b mod m,a从1开始标号 int X[N], y[N]; boolmod_Xn_equation(int a[], int b, int m, int n, int x[]) { a[n + 1] = m; int d = a[1]; for (int i = 2; i <= n + 1; i++) d = exgcd(d, a[i], X[i - 1], y[i - 1]); // 这个exgcd返回求解的ax+by=d的 if (b % d) returnfalse; int c = b / d; x[n + 1] = y[n] * c; y[0] = 1; for (int i = n; i >= 1; i--) { c = (c * X[i] % m + m) % m; x[i] = (y[i - 1] * c % m + m) % m; } returntrue; }
高次同余方程
只考虑:ax≡b(modm)
为保持统一,放一下手写哈希
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// (x,y)的HASH #define MOD 76543 int hs[MOD], head[MOD], nxt[MOD], id[MOD], top; voidinsert(int x, int y) { int k = x % MOD; hs[top] = x, id[top] = y, nxt[top] = head[k], head[k] = top++; } intfind(int x) { int k = x % MOD; for (int i = head[k]; i != -1; i = nxt[i]) if (hs[i] == x) return id[i]; return-1; }
// 普通BSGS: a^x==b mod m, gcd(a,m)=1 intBSGS(int a, int b, int m) { if(b == 1 || m == 1) // 注意这里的特判 return0; int s = sqrt(m) + 1; memset(head,-1,sizeof(head)); top=0; for (int i = 0, tmp = b; i < s; i++, tmp = tmp * a % m) insert(tmp, i); int as = qpow(a, s, m); // 快速幂算a^s for (int i = 1, tmp = as; i <= s + 1; i++, tmp = tmp * as % m) { int qry = find(tmp); if (qry == -1) continue; return i * s - qry; } return-1; }
intexBSGS(int a, int b, int m) { if (b == 1 || m == 1) return0; int k = 0, atmp = 1; while (1) { int tmp = __gcd(m, a); if (tmp == 1) break; if(b % tmp) return-1; b /= tmp, m /= tmp, k++; atmp = atmp * (a / tmp) % m; if (b == atmp) return k; } // 此时b=b/D, m=m/D, atmp=a^k / D int ans = BSGS(a, b * inv(atmp, m) % m, m); return ans == -1 ? ans + k; }