zoukankan      html  css  js  c++  java
  • 中国剩余定理

    蓝书

    同余方程组:形如$x equiv a_i(mod\,m_i)$的n个方程(各个$m_i$两两互质;好像$m_i=1$时以下一些会不成立?然而不要紧)

    令$M=prod_{i=1}^n m_i$

    令$w_i=M/m_i$

    根据各个$m_i$两两互质,可得$w_i$与$m_i$互质

    找出$p_i$等于$w_i$关于$m_i$的乘法逆元;则$p_i*w_i equiv 1(mod\,m_i)$

    令$x_0=sum_{i=1}^n a_i*p_i*w_i$

    显然,对于第i个方程,$x_0 equiv a_i*p_i*w_i equiv a_i(mod\,m_i)$(因为对于$j!=i$,$w_j equiv 0(mod\,m_i)$)

    得到了一组可行解;则任意解即为$x_0+k*M$,k为任意整数


    扩展

    各数不互质?

    换一种方法:两两合并

    现在已知形如$x equiv a_i(mod\,m_i)$的2个方程,$m_i$不需要互质

    设$x=k_1*m_1+a_1$,$x=(-k_2)*m_2+a_2$

    那么$k_1*m_1+k_2*m_2=a_2-a_1$

    可以用exgcd解出一组合法的$k_1$和$k_2$(当然没有合法解就不存在方程组的解)

    因此$x equiv k_1*m_1+a_1(mod\,lcm(m_1,m_2))$


    弃用

    用exgcd找出每个$p_i$,使得$p_i*w_i+q_i*m_i=1$(实际上就是$p_i$是$w_i$关于$m_i$的乘法逆元)

    那么两边模$m_i$,得到$p_i*w_i equiv 1(mod\,m_i)$(因为$p_i$,$w_i$都显然不为$m_i$的倍数)


    例题

    Strange Way to Express Integers POJ - 2891

    错误记录:

    32行k1也要取模,根据exgcd的解的通式,取模的对象是m[i]/g

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pi;
    13 //xa+yb=1
    14 void exgcd(ll a,ll b,ll &g,ll &x,ll &y)
    15 {
    16     if(!b)    {x=1;y=0;g=a;}
    17     else    {exgcd(b,a%b,g,y,x);y-=x*(a/b);}
    18 }
    19 ll Mod(ll a,ll b)
    20 {
    21     if(a>=0)    return a%b;
    22     else    if(a%b==0)    return 0;
    23     else    return b+a%b;
    24 }
    25 ll ex_china(ll n,ll *a,ll *m)
    26 {
    27     ll i,k1,k2,g,lm=m[0],la=Mod(a[0],m[0]),t;
    28     for(i=1;i<n;i++)
    29     {
    30         exgcd(lm,m[i],g,k1,k2);
    31         if((a[i]-la)%g!=0)    return -1;
    32         t=m[i]/g;k1=Mod(k1*((a[i]-la)/g),t);t*=lm;
    33         la=Mod(k1*lm+la,t);lm=t;
    34     }
    35     return la;
    36 }
    37 ll n,a[100100],m[100100];
    38 int main()
    39 {
    40     ll i;
    41     while(scanf("%lld",&n)==1)
    42     {
    43         for(i=0;i<n;i++)    scanf("%lld%lld",&m[i],&a[i]);
    44         printf("%lld
    ",ex_china(n,a,m));
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    程序员有哪些发展方向
    Mysql Join语法解析与性能分析
    jQuery过滤性选择器
    jQuery 基础选择器
    CSS布局模型
    CSS 盒子模型
    CSS 的继承、层叠和特殊性
    java 集合框架(一)
    从客户端中检测到有潜在危险的 Request.Form 值
    线程的一些问题
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9275611.html
Copyright © 2011-2022 走看看