zoukankan      html  css  js  c++  java
  • 中国剩余定理学习笔记

    中国剩余定理学习笔记。

    前置技能:扩展欧几里得算法。

    中国剩余定理

    对于这样一个模方程组:

    [egin{cases} x=r_1\%m_1 \ x=r_2\%m_2 \ ...... \ x=r_n\%m_n end{cases} ]

    其中(m_1,m_2,...m_n)两两互质。

    (x)的最小正整数解。

    定理:

    (M=prod_{i=1} ^{n}m_i),因为其两两互质,所以(M)为他们的最小公倍数。

    (t_i)为方程$ frac M{m_i}*t_i=1(mod,m_i) $的解

    很显然可以利用扩展欧几里得解出(t_i)

    对于当前的模方程,我们只用和上一组通解合并即可。

    通解为(x_i=x_0+i*M);

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int a[15],b[15];
    
    void exgcd(int a,int b,int &d,int &x,int &y) {
    	if(b)exgcd(b,a%b,d,y,x),y-=(a/b)*x;
    	else d=a,y=0,x=1;
    }
    
    int main() {
    	int n,ans=0,sum=1,d,y;
    	scanf("%d",&n);
    	for(int i=0; i<n; i++)
    		scanf("%d%d",&a[i],&b[i]);
    	for(int i=0; i<n; i++) sum*=a[i];
    	for(int i=0; i<n; i++) {
    		int w=sum/a[i];
    		exgcd(a[i],w,d,d,y);
    		ans=(ans+y*w*b[i])%sum;
    	}
    	ans=(ans+sum)%sum;
    	printf("%d",ans);
    }
    

    扩展中国剩余定理

    同上,只是(m_i)不一定互质。

    推导

    (m)个方程组的解集为(Ans+M*K),现在合并下一个方程。

    当前方程为(x=r_i(mod,m_i))

    则问题装换为,找到一个最小的(t)

    满足(Ans+t*M+m_i*y=r_i),

    (t*M+m_i*y=r_i-Ans);

    由于(M)(m_i)都是已知量,我们利用扩展欧几里得即可,

    解出(t),带回合并即可。

    代码

    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define int long long
    #define reg register
    #define debug(x) cerr<<#x<<" = "<<x<<endl;
    #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
    #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
    #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
     
    inline int Read() {
        int res=0,f=1;
        char c;
        while(c=getchar(),c<48||c>57)if(c=='-')f=0;
        do res=(res<<3)+(res<<1)+(c^48);
        while(c=getchar(),c>=48&&c<=57);
        return f?res:-res;
    }
     
    template<class T>inline bool Min(T &a,T const&b) {
        return a>b?a=b,1:0;
    }
    template<class T>inline bool Max(T &a,T const&b) {
        return a<b?a=b,1:0;
    }
     
    const int N=1e5+5;
    const int dx[4]= {1,-1,0,0},dy[4]= {0,0,1,-1};
    
    int n,mod[N],res[N];
    
    int Exgcd(int a, int b, int &x, int &y) {
    	if(!b) {
    		x=1,y=0;
    		return a;
    	}
    	int g=Exgcd(b,a%b,y,x);
    	y-=(a/b)*x;
    	return g;
    }
    
    inline int Excrt() {
    	int M=mod[1],ans=res[1],x,y;
    	rep(i,2,n){
    		int g=Exgcd(M,mod[i],x,y);
    		if((res[i]-ans)%g) return -1;
    		x*=(res[i]-ans)/g,y=mod[i]/g, x=(x%y+y)%y;
    		ans=M*x+ans, M=M/g*mod[i], ans%=M;
    	}
    	int z=(ans%M+M)%M;
    	if(!z)z=M;
    	return z;
    }
    
    signed main() {
    	scanf("%lld",&n);
    	rep(i,1,n)mod[i]=Read(),res[i]=Read();
    	int Ans=Excrt();
    	printf("%lld
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    python数据分析之csv/txt数据的导入和保存
    SQL Server日志文件过大 大日志文件清理方法 不分离数据库
    socket--多进程,多线程服务器
    MYSQL千万级数据表,创建表及字段扩展的几条建议
    常见WEB攻击
    jQuery学习笔记之Ajax用法详解
    redis范围查询应用 数据库 数据库学习 Redis redis范围查询的方法
    CentOS 7下使用RPM安装mysql的方法。
    MySQL Daemon failed to start错误解决办法是什么呢?
    windows无法启动MySQL服务报错1067的解决方法是怎样?
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11562909.html
Copyright © 2011-2022 走看看