中国剩余定理

来源:互联网 发布:siesta软件是啥 编辑:程序博客网 时间:2024/06/07 18:58

中国剩余定理

//又名“王冠博”定理。——不要问我为什么
主要用来解决一元线性同余方程组

*以下内容摘自曹冲养猪

假如有16头母猪,如果建了3个猪圈,剩下1头猪就没有地方安家了。如果建造了5个猪圈,但是仍然有1头猪没有地方去,然后如果建造了7个猪圈,还有2头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?

中国【天朝】剩余定理就是解决这种问题的。


代码部分:

  • 用a[]保存 取模的数,b[]保存剩下的余数
  • M为 ∏a[i]

然后求解 Ma[i] x1  (mod a[i])
这就用到了 Ex_gcd 求解的 x 就是取模a[i] 为 1 的值
但是需要乘 b[i] 才是答案

注意有如下两个性质

  1. 求得的结果满足第 i 个同余方程
  2. 且 mod 剩下的 a[j] 为 0 【因为M中包含了a[j]】

把所有的结果累加起来就是答案,但是注意x可能为负数,所以要+mod)%mod
Code:

#include <stdio.h>#include <string.h>#define MAXN 100typedef long long ll;ll n,x=1,y=0,ret;ll a[MAXN],b[MAXN];void Ex_gcd(ll a,ll b){    if(b==0)    {        x=1;        y=0;    }    else     {        Ex_gcd(b,a%b);        ll t=x;        x=y;        y=t-a/b*x;    }}void CRT(){    ll M=1;         //∏a[i]    for(ll i=1;i<=n;i++)    {        M=M*a[i];     }    for(ll i=1;i<=n;i++)    {        ll m=M/a[i];        Ex_gcd(m,a[i]);         //求 (M/a[i]) * x  =   b[i]  (Mod a[i])          x=(x%a[i]+a[i])%a[i];        ret=(ret+x*b[i]*m%M)%M;    }}int main(){    scanf("%lld",&n); //条件个数     for(ll i=1;i<=n;i++)    {        scanf("%lld%lld",&a[i],&b[i]);   // a[i] 表示 取模的数   b[i]   表示 余数     }    CRT();    printf("%lld\n",ret);    return 0;} 
1 0
原创粉丝点击