SQL-報錯注入
阿新 • • 發佈:2022-05-16
中國剩餘定理
構造法(只適用模數兩兩互質的情況,CRT的本質思想)
-
對於解線性同餘方程組 useless,因為完全可以被增量法代替
-
但是揭示了若模數兩兩互質,則線性同餘方程組一定有解。
若模數為合數 \(q\), \(q=p_1^{e_1}*p_2^{e_2}*p_3^{e_3}*...p_k^{e_k}\)
-
\(x\mod q = a\iff x \mod p_i^{e_i}=a \;同時成立\)
-
若給出一個模數不一定為質數線性方程組,判斷是否有解,可將每個模數拆成 素數冪 的形式
對於底數相同的方程分到一組,可先假設冪最高的成立,這樣就很容易檢查冪低的是否矛盾,若有矛盾則無解
因為此時每一組之間的模數都是兩兩互質的,所以只要組中沒有矛盾,則該方程組一定有解
-
中國剩餘定理2 - 題目 - Daimayuan Online Judge
性質 2.2 的應用
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <map> using namespace std; typedef long long ll; typedef pair<int, int> PII; const int N = 1e5 + 10; //[p, [s, a]] 為該組以p為底,p的冪為s, x mod s = a map<int, vector<PII> > mp; bool solve() { int n; scanf("%d", &n); mp.clear(); while(n--) { int a, m; scanf("%d%d", &a, &m); for (int i = 2; i <= m / i; i++) { if (m % i) continue; int s = 1; while(m % i == 0) { s *= i; m /= i; } mp[i].push_back({s, a % s}); } if (m > 1) mp[m].push_back({m, a % m}); } for (auto t : mp) { int p = t.first; //找到該組冪最大的 int now = max_element(mp[p].begin(), mp[p].end())->second; for (auto i : mp[p]) { if (now == -1) now = i.second; if (now % i.first != i.second) return false; } } return true; } int main() { int T; scanf("%d", &T); while(T--) { if (solve()) puts("Yes"); else puts("No"); } return 0; }
增量法 (適用於模數不一定兩兩互質的情況)
給定 \(n\) 個方程,求 \(x\) ,滿足 \(x\equiv a_i\;(mod \;m_i)\), 且 \(0<=x<lcm(m_1,m_2...m_n)\)
可逐一合併兩個同餘方程,最後剩下的同餘方程 \(x \equiv a \;(mod \;lcm(m_1,m_2...m_n))\) 的 \(a\) 就是答案
合併兩個同餘方程的過程為:
\[\begin{aligned} &1.\\ &x\equiv a\;(mod\;b)\\ &x\equiv c\;(mod\;d)\\ &x=b*t+a,\;所以解出\;t\;即可\\ &帶入第二個同餘方程得:b*t\equiv c-a\;(mod\;d)\\ &令\;g=exgcd(b,d)\\ &若\;g\nmid c-a,\; 則\;該同餘方程組無解\\ &2.\\ &否則在\;g=exgcd(b,d)\;中解得的\;t_0\;為\;b*t+d*s=g\;的一個\;t\;的解\\ &令\;d'=\frac dg\;則通解\;t=t_0+d'*y\;(y\;為常數)\\ &此時找到最小的一個非負整數解\;t_0,即若\;t_0<0\;則\;t_0=t_0+d'\\ &3.\\ &令\;t_0=t_0*\frac {c-a}g,\;此時\;t_0\;為\;b*t+d*s=c-a\;的一個解\\ &即\;t_0\;為\;b*t\equiv c-a\;(mod\;d)\;的解\\ &通解仍為\;t=t_0+d'*y\;(y\;為常數)\\ &4.\\ &x=b*t+a=b*(t_0+d'*y)+a=b*d'*y+b*t_0+a\\ &因此\;x\equiv b*t_0+a\;(mod\;b*d') \end{aligned} \] 中國剩餘定理 - 題目 - Daimayuan Online Judge
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
ll xx, yy;
ll d = exgcd(b, a % b, xx, yy);
x = yy, y = xx - a / b * yy;
return d;
}
void merge(ll &a, ll &b, ll c, ll d) // d <= 1e9, b可能很大
{
// bt = c - a (mod d)
if (a == -1 && b == -1)
return;
ll x, y;
ll g = exgcd(b, d, x, y);
if ((c - a) % g != 0)
{
a = b = -1;
return;
}
d /= g; // d'
ll t0 = ((c - a) / g) % d * x % d; // 注意 c - a 可能很大,及時取模
//t = t0 (mod d')
if (t0 < 0) t0 += d; // 若為負數則 + 模數 就是最小非負整數
a = b * t0 + a;
b = b * d;
}
void solve()
{
int n;
scanf("%d", &n);
ll a = 0, b = 1; //當前的方程為 x mod b = a,每次迭代合併一個 x mod c = d
for (int i = 1; i <= n; i++)
{
ll c, d;
scanf("%lld%lld", &c, &d);
merge(a, b, c, d);
}
printf("%lld\n", a);
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
solve();
return 0;
}
並且中國剩餘定理可以推出:
\(q=p_1^{e_1}*p_2^{e_2}*p_3^{e_3}*...p_k^{e_k}\)
$