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

    前言

    题目链接

    戳我

    前置知识

    1. 乘法逆元
    2. 扩展欧几里得
    3. 一些简单的数学知识(小学奥数)

    正文

    引子

    在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。

    在《孙子歌诀》中给出了解决这个问题的解法:三人同行七十稀,五树梅花廿一支,七子团圆正半月,除百零五便得知。很是朗朗上口,但这是什么意思呢?

    具体解法分三步:
    找出三个数:
    1.从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
    2.用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加(152+213+70*2)得到和233。
    3.用233除以3,5,7三个数的最小公倍数105,得到余数23,即233%105=23。这个余数23就是符合条件的最小数。

    说实话我不知道这是怎么想出来的,tql。

    现在原问题可以化成:

    [ f(x)=left{ egin{aligned} x≡a_1 pmod{m_1} \ x≡a_2 pmod{m_2}\ x≡a_3 pmod{m_3}\ x≡a_4 pmod{m_4}\ end{aligned} ight. ]

    现在假设$m_1,m_2,m_3,m_4,...,m_n相互互质,则可以进行如下构造

    令:$$M=prod_{i=1}^nm_i$$设:$$M_i=M/m_i,t_i=exgcd(M_i,m_i).x$$
    则x的通解为:

    [x=KM+sum_{i=1}^na_i*t_i*M_i ]

    所以最小的x为:

    [x=sum_{i=1}^na_i*t_i*M_i ]

    然后直接算就好了

    code

    #include<bits/stdc++.h>
    #define rg register
    #define int long long
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    int read(){
        int x=0,f=1;
    	char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    void exgcd(int a,int b ,int &x,int &y){
    	if(!b){x=1,y=0;return;}
    	exgcd(b,a%b,x,y);
    	int t=x;
    	x=y,y=t-(a/b)*y;
    }
    int n,x,y,a[11],p[11];
    void crt(){
    	int ans=1,js=0;
    	for(int i=1;i<=n;i++)
    		ans*=p[i];
    	for(int i=1;i<=n;i++){
    		int t=ans/p[i];
    		exgcd(t,p[i],x,y);
    		js+=a[i]*t%ans*x%ans;
    		js%=ans;
    	}
    	printf("%lld",(js+ans)%ans);
    }
    void init(){
    	n=read();
    	for(int i=1;i<=n;i++)
    		p[i]=read(),a[i]=read();
    }
    main(){
    //	file("");
    	init();
    	crt();
    	return 0;
    }
    
  • 相关阅读:
    考拉兹猜想,100万以内的数
    给任意a、b、c三个数作为边盘都是否能构成三角形
    计数算法-对200万考生的成绩就行排序
    冒泡排序
    插入排序
    Echarts
    vue+tinymce
    java RestTemplate.postForObject请求传参
    java计算今天起后7天时间 +昨天八点+今天前7天的日期
    layui+echarts+动态数据
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10198735.html
Copyright © 2011-2022 走看看