zoukankan      html  css  js  c++  java
  • LG4777 【模板】扩展中国剩余定理(EXCRT)

    题意

    题目描述

    给定(n)组非负整数(a_i, b_i),求解关于(x)的方程组

    [egin{cases} x equiv b_1 ({ m mod} a_1) \ xequiv b_2 ({ m mod} a_2) \ ... \ x equiv b_n ({ m mod} a_n)end{cases}$$的最小非负整数解。 ## 输入输出格式 ### 输入格式: 输入第一行包含整数$n$。 接下来$n$行,每行两个非负整数$a_i, b_i$。 ### 输出格式: 输出一行,为满足条件的最小非负整数$x$。 ## 输入输出样例 ### 输入样例#1: 3 11 6 25 9 33 17 ### 输出样例#1: 809 ## 说明 $n leq 10^5, 1 leq a_i leq 10^{12}, 0 leq b_i leq 10^{12}, b_i < a_i$,保证答案不超过$10^{18}$。 请注意程序运行过程中进行乘法运算时结果可能有溢出的风险。 数据保证有解 # [niiick](https://www.luogu.org/blog/niiick/solution-p4777)的题解 问题 求解同余方程组 ]

    left{egin{aligned}xequiv a_1(mod m_1) quad xequiv a_2(mod m_2) quad xequiv a_3(mod m_3) quad ...quadxequiv a_k(mod m_k) quadend{aligned} ight.

    [其中$m_1,m_2,m_3...m_k$为不一定两两互质的整数, 求x的最小非负整数解 求解 假设已经求出前k-1个方程组成的同余方程组的一个解为x 且有$M=prod_{i-1}^{k-1}m_i$(补充:代码实现中用的就是$M=LCM_{i-1}^{k-1}m_i$,显然易证这样是对的,还更能防止溢出,上述是为了先方便理解 则前k-1个方程的方程组通解为$x+i*M(iin Z)$ 那么对于加入第k个方程后的方程组 我们就是要求一个正整数t,使得$x+t*M equiv a_k(mod m_k)$ 转化一下上述式子得$t*M equiv a_k-x(mod m_k)$ 对于这个式子我们已经可以通过扩展欧几里得求解t 若该同余式无解,则整个方程组无解, 若有,则前k个同余式组成的方程组的一个解解为$x_k=x+t*M$ 所以整个算法的思路就是求解k次扩展欧几里得 ```cpp #include<bits/stdc++.h> #define rg register #define il inline #define co const template<class T>il T read(){ rg T data=0,w=1; rg char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') w=-1; ch=getchar(); } while(isdigit(ch)) data=data*10+ch-'0',ch=getchar(); return data*w; } template<class T>il T read(rg T&x){ return x=read<T>(); } typedef long long ll; co int maxn=1e5+1; int n; ll ai[maxn],bi[maxn]; ll mul(ll a,ll b,ll mod){ ll re=0; while(b){ if(b&1) re=(re+a)%mod; a=(a+a)%mod; b>>=1; } return re; } ll exgcd(ll a,ll b,ll&x,ll&y){ if(b==0) {x=1,y=0;return a;} ll gcd=exgcd(b,a%b,x,y); ll z=x;x=y;y=z-y*(a/b); return gcd; } ll excrt(){ ll x,y; ll M=bi[1],ans=ai[1]; for(int i=2;i<=n;++i){ ll a=M,b=bi[i],c=(ai[i]-ans%b+b)%b; ll gcd=exgcd(a,b,x,y),bg=b/gcd; if(c%gcd) return -1; x=mul(x,c/gcd,bg); ans+=x*M; M*=bg; ans=(ans%M+M)%M; } return ans; } int main(){ // freopen(".in","r",stdin),freopen(".out","w",stdout); read(n); for(int i=1;i<=n;++i) read(bi[i]),read(ai[i]); printf("%lld ",excrt()); return 0; } ```]

  • 相关阅读:
    Minecraft 1.12.2/1.14.4 Mod开发笔记——搭建环境
    Minecraft 1.12.2 Mod开发笔记
    浅谈莫比乌斯反演
    卡迈克尔数
    一些可能会有用的东西(持续更新)
    emacs配置
    CSPS 2020游记
    浅谈KMP
    Atcoder AGC052
    乌班图操作指令(持续更新)
  • 原文地址:https://www.cnblogs.com/autoint/p/extended_chinese_remainder_theorem.html
Copyright © 2011-2022 走看看