• 中国剩余定理


    中国剩余定理

    求解模线性方程组。

    {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. }
  • 相关阅读:
    数学建模——最大流问题(配合例子说明)
    计算机网络笔记 第三章数据链路层
    零基础非计算机专业转行软件测试可行吗?
    MySQL锁
    MAC 通过IDEA启动tomcat,显示80端口被占用解决办法
    JWT原理
    知识分享 钡铼网关功能介绍:使用SSLTLS 加密,保证MQTT通信安全
    不做工程等于纸上谈兵——对话OceanBase创始人阳振坤
    Jmeter---非GUI命令行的执行生成报告、使用ant插件执行接口测试脚本生成报告
    Facebook又双叒崩了!网友:扎克伯格一周只用上三天班?
  • 原文地址:https://blog.csdn.net/KonjakuLAF/article/details/126237492