• 中国剩余定理


    中国剩余定理

    求解模线性方程组。

    {x1a1(modr1)x2a2(modr2)xkak(modrk)" role="presentation" style="text-align: center; position: relative;">{x1a1(modr1)x2a2(modr2)xkak(modrk)

    crt

    r1,r2,,rk" role="presentation" style="position: relative;">r1,r2,,rk 为互质的,设 M=i=1kri,Ai=Mri" role="presentation" style="position: relative;">M=i=1kri,Ai=Mri ,可的 M" role="presentation" style="position: relative;">Mr1,,rk" role="presentation" style="position: relative;">r1,,rk 的 lcm

    可得 Ai,ri" role="presentation" style="position: relative;">Ai,ri 是互质的,则必存在 Ai" role="presentation" style="position: relative;">Airi" role="presentation" style="position: relative;">ri 意义下的逆元 ti" role="presentation" style="position: relative;">ti 使得 Aiti1(modri)" role="presentation" style="position: relative;">Aiti1(modri)

    xi=aiAiti" role="presentation" style="position: relative;">xi=aiAiti 是满足第 i" role="presentation" style="position: relative;">i 个方程的。同时 ji" role="presentation" style="position: relative;">ji ,都有 xi0(modrj)" role="presentation" style="position: relative;">xi0(modrj) ,因为 Ai" role="presentation" style="position: relative;">Ai 中有一个因子 rj" role="presentation" style="position: relative;">rj

    可以得到通解 x=i=1kaiAiti+pM(pZ)" role="presentation" style="position: relative;">x=i=1kaiAiti+pM(pZ) 。显然满足条件

    1. #include
    2. using namespace std;
    3. typedef unsigned long long uLL;
    4. typedef long double LD;
    5. typedef long long LL;
    6. typedef double db;
    7. const int N = 55;
    8. LL exgcd(LL a, LL b, LL &x, LL &y) {
    9. if (!b) return x = 1, y = 0, a;
    10. register LL gcd = exgcd(b, a % b, y, x);
    11. return y -= a / b * x, gcd;
    12. }
    13. inline LL inv(LL a, LL b) {
    14. register LL x, y;
    15. exgcd(a, b, x, y);
    16. return (x % b + b) % b;
    17. }
    18. int n;
    19. LL a[N], r[N], mul = 1, A[N], ans;
    20. int main() {
    21. scanf("%d", &n);
    22. for (int i = 1; i <= n; i++) scanf("%lld%lld", &r[i], &a[i]), mul *= r[i];
    23. for (int i = 1; i <= n; i++) {
    24. A[i] = mul / r[i];
    25. ans += a[i] * A[i] * inv(A[i], r[i]);
    26. }
    27. printf("%lld", ans % mul);
    28. }

    excrt

    r1,,rk" role="presentation" style="position: relative;">r1,,rk 不互质,此时使用扩展 crt

    {x1a1(modr1)x2a2(modr2)xkak(modrk)" role="presentation" style="text-align: center; position: relative;">{x1a1(modr1)x2a2(modr2)xkak(modrk)

    看前两个方程。

    x=kr1+a1=pr2+a2" role="presentation" style="position: relative;">x=kr1+a1=pr2+a2 ,其中 k,pZ" role="presentation" style="position: relative;">k,pZ

    kr1pr2=a2a1" role="presentation" style="position: relative;">kr1pr2=a2a1 ,这是形如 ax+by=c" role="presentation" style="position: relative;">ax+by=c 的形式,用 exgcd 求解。

    此处可得 gcd(r1,r2)(a2a1)" role="presentation" style="position: relative;">gcd(r1,r2)(a2a1) 时无解。

    求出一个解 k0" role="presentation" style="position: relative;">k0 ,则通解 k=k0+or2gcd(r1,r2)(oZ)" role="presentation" style="position: relative;">k=k0+or2gcd(r1,r2)(oZ)

    k" role="presentation" style="position: relative;">k 带入 kr1+a1" role="presentation" style="position: relative;">kr1+a1 可得

    (k0+or2gcd(r1,r2))r1+a1=k0r1+a1+olcm(r1,r2)" role="presentation" style="text-align: center; position: relative;">(k0+or2gcd(r1,r2))r1+a1=k0r1+a1+olcm(r1,r2)

    xk0r1+a1(modlcm(r1,r2))" role="presentation" style="position: relative;">xk0r1+a1(modlcm(r1,r2))

    相当于合并了两个方程,合并 n1" role="presentation" style="position: relative;">n1 次即可得到答案。

    注意 k0" role="presentation" style="position: relative;">k0 应乘上 a2a1gcd(r1,r2)" role="presentation" style="position: relative;">a2a1gcd(r1,r2)

    模板题需要用龟速乘。

    1. #include
    2. using namespace std;
    3. typedef unsigned long long uLL;
    4. typedef long double LD;
    5. typedef long long LL;
    6. typedef double db;
    7. const int N = 100005;
    8. LL exgcd(LL a, LL b, LL &x, LL &y) {
    9. if (!b) return x = 1, y = 0, a;
    10. register LL gcd = exgcd(b, a % b, y, x);
    11. return y -= a / b * x, gcd;
    12. }
    13. LL G;
    14. inline LL mul(LL x, LL y, LL p) {
    15. return (x * y - (LL)((LD)x / p * y) * p + p) % p;
    16. }
    17. inline bool sol(LL a, LL b, LL c, LL &x, LL &y) {
    18. G = exgcd(a, b, x, y);
    19. register LL t;
    20. if (c % G) return false;
    21. t = b / G;
    22. x = mul(x, c / G, t);
    23. x = (x + t) % t;
    24. y = (c - a * x) / b;
    25. return true;
    26. }
    27. int n, isL;
    28. LL a[N], r[N];
    29. int main() {
    30. scanf("%d", &n);
    31. for (int i = 1; i <= n; i++) scanf("%lld%lld", &r[i], &a[i]);
    32. isL = 1;
    33. for (int i = 1; i < n; i++) {
    34. register LL x, y;
    35. if (!sol(r[i], r[i + 1], a[i + 1] - a[i], x, y)) {
    36. isL = 0; break;
    37. }
    38. a[i + 1] = x * r[i] + a[i];
    39. r[i + 1] = r[i] / G * r[i + 1];
    40. }
    41. printf("%lld", a[n]);
    42. }
  • 相关阅读:
    数据交换格式(XML与JSON)、JSON与JavaScript对象之间互转
    前端性能精进(七)——构建
    [数据结构] 图---求解多源最短路径:实现弗洛伊德算法
    Python分享之数学与随机数 (math包,random包)
    使用uni-app创建扫码连接wifi小程序
    MySQL总结
    vscode launch.json
    java泛型场景补充注意事项
    nestjs 新手入门第一章从入门到弃坑 解决运行中的启动错误
    02_udp编程
  • 原文地址:https://blog.csdn.net/KonjakuLAF/article/details/126237492