zoukankan      html  css  js  c++  java
  • 扩展中国剩余定理(EXCRT)小记

    前言

    其实(EXCRT)也并不像想象中那么难嘛。

    记得之前学的时候翻了好多博客都看不懂,现在可能是因为找到一篇通俗易懂的题解,一下就把这个算法搞明白了。

    同余方程

    给定一个如下形式的方程:

    [egin{cases} xequiv b_1( exttt{mod} a_1)\ xequiv b_2( exttt{mod} a_2)\ vdots\ xequiv b_n( exttt{mod} a_n) end{cases} ]

    (CRT)不同的是,(EXCRT)可以求解(a_1,a_2,...,a_n)不互质的情况。

    算法流程

    考虑我们从左向右扫,维护前(i-1)个同余方程的答案(ans)以及前(i-1)(a)的最小公倍数(M)

    现在我们要修改(ans)让它在依然满足前(i-1)个方程的同时满足第(i)个方程。

    发现只要我们给(ans)加上的数是(M)的倍数,它就必然依旧满足前(i-1)个方程。

    于是我们考虑列出一个不定方程:

    [ans+Mx=b_i+a_iy ]

    移项得到:

    [Mx-a_iy=b_i-ans ]

    这里由于我们并不需要知道(y)的具体值,其实也可以写成(Mx+a_iy=b_i-ans),主要看个人习惯。

    至于这个方程明显是可以(exgcd)求解的。

    然后只要给(ans)加上(Mx),更新(M)(lcm(M,a_i)),继续做下去就好了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define LL long long
    #define N 100000
    using namespace std;
    int n;LL a[N+5],b[N+5];
    I LL QM(LL x,LL y,LL X) {LL k=(1.0L*x*y)/X,t=x*y-k*X;t-=X;W(t<0) t+=X;return t;}//快速乘
    I LL exgcd(LL x,LL y,LL& a,LL& b) {LL g;return y?(g=exgcd(y,x%y,b,a),b-=a*(x/y),g):(a=1,b=0,x);}//exgcd解不定方程
    int main()
    {
    	RI i;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%lld%lld",a+i,b+i);
    	LL ans=b[1],M=a[1],g,A,B;for(i=2;i<=n;++i) A=B=0,g=exgcd(M,a[i],A,B),//ans维护答案,M维护lcm
    		ans+=QM(A,(b[i]-ans%a[i]+a[i])%a[i]/g,a[i]/g)*M,M*=a[i]/g,ans=(ans%M+M)%M;//更新ans和M,注意先更新M再取模
    	return printf("%lld
    ",ans),0;
    }
    
  • 相关阅读:
    js根据ip地址获取城市地理位置
    vue-cli项目中使用mock结合axios-mock-adapter生成模拟数据
    将图片转canvas
    判断浏览器是否联网
    头尾固定中间高度自适应布局 css
    经典闭包
    多余文字转化为省略号css
    $.grep()
    node 图片转base64
    CentOS 7下安装Mysql 5.7
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/EXCRT.html
Copyright © 2011-2022 走看看