• sss


    <更新提示>

    <第一次更新>
    <第二次更新> 更新了(Ex-CRT)的内容


    <正文>

    线性同余方程

    定义

    给定整数(a,b,m),对于形如(axequiv b(mod m))的同余方程我们称之为一次同余方程,即线性同余方程。

    解线性同余方程

    对于此类方程,我们可以用如下方法快速的求解。

    [axequiv b(mod m)⇔m|ax-b ]

    不妨设(-ym=ax-b),则可以将方程改写为(ax+my=b),该不定方程可以使用扩展欧几里得算法快速地求解(详见『扩展欧几里得算法 Extended Euclid』)。

    对于(gcd(a,m) ot |b)的情况,也可以直接判定为原方程无解。

    对于使用扩展欧几里得算法求解出来的一个解(x_0),所有模(frac{m}{gcd(a,m)})意义下与(x_0)同余的整数都是方程的解,这是可以由不定方程的通解公式得到的。通常来说,我们需要求解最小非负整数解时,可以使用取模操作让(x)落在(0)(frac{m}{gcd(a,m)}-1)的范围内,就得到了最小解。

    同余方程(NOIP2012)

    Description

    求关于 x 的同余方程 ax≡1(mod b) 的最小正整数解。

    Input Format

    输入只有一行,包含两个正整数 a,b,用一个空格隔开。

    Output Format

    输出只有一行,包含一个正整数 x0,即最小正整数解。输入数据保证一定有解。

    Sample Input

    3 10
    

    Sample Output

    7
    

    解析

    模板题,将方程化为(ax+by=1),用扩展欧几里得算法求解。由于数据保证(bgeq2),所以不存在(x=0)的解,利用取模操作就能保证得到的解是最小整数解。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    inline long long Exeuclid(long long a,long long &x,long long b,long long &y,long long c)
    {
    	if (b==0){x=c/a,y=0;return a;}
    	else 
    	{
    		long long p=Exeuclid(b,x,a%b,y,c);
    		long long x_=x,y_=y;
    		x=y_;y=x_-a/b*y_;
    		return p;
    	}
    }
    long long A,B,X,Y;
    int main(void)
    {
    	scanf("%lld%lld",&A,&B);
    	long long p=Exeuclid(A,X,B,Y,1);
    	printf("%lld
    ",(X%(B/p)+(B/p))%(B/p));
    	return 0;
    }
    

    中国剩余定理

    描述

    对于形如

    [egin{cases} x equiv a_1(mod m_1) \ x equiv a_2(mod m_2) \ ... \ x equiv a_n(mod m_n) end{cases} ]

    (n)个线性同余方程组成的线性同余方程组,如果有模数(m_1,m_2,...,m_n)两两互质,则方程组一定有解,解为(x=sum_{i=1}^{n}a_iM_it_i)

    其中,(m=prod_{i=1}^nm_i)(M_i=frac{m}{m_i})(t_i)为线性同余方程(M_it_i equiv 1(mod m_i))的一个解。

    证明:
    由于(t_i)为线性同余方程(M_it_i equiv 1(mod m_i))的一个解,所以对于(forall i,a_iM_it_i equiv a_i(mod m_i))成立,又因为(M_i)是除了(m_i)以外所有模数的倍数,即对于(forall k ot =i,a_iM_it_i equiv 0(mod m_k)),所以解(x=sum_{i=1}^{n}a_iM_it_i)对方程(x equiv a_i(mod m_i))也成立,故该解对于每一个方程都成立。

    对于该同余方程组,其通解可以表示为(x+km(kin Z)),对于最小非负整数解,也是通过取模(m)的操作就可以了。

    曹冲养猪

    Description

    自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。

    举个例子,假如有16头母猪,如果建了3个猪圈,剩下1头猪就没有地方安家了。如果建造了5个猪圈,但是仍然有1头猪没有地方去,然后如果建造了7个猪圈,还有2头没有地方去。

    你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?

    Input Format

    第一行包含一个整数n (n <= 10) – 建立猪圈的次数,

    解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示建立了ai个猪圈,有bi头猪没有去处。你可以假定ai,aj互质.

    Output Format

    输出包含一个正整数,即为曹冲至少养母猪的数目。

    Sample Input

    3
    3 1
    5 1
    7 2
    

    Sample Output

    16
    

    解析

    中国剩余定理模板题,我们直接利用(Exeuclid)算法和线性同余方程的知识,解出(t_i),然后构造最小非负整数解即可。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    #define mset(name,val) memset(name,val,sizeof name)
    const int N=12;
    long long a[N],m[N],M[N],t[N],n,m_,ans;
    inline void input(void)
    {
        scanf("%lld",&n);
        for (int i=1;i<=n;i++)
            scanf("%lld%lld",&m[i],&a[i]);
    }
    inline long long Exeuclid(long long a,long long &x,long long b,long long &y,long long c)
    {
        if (b==0){x=c/a,y=0;return a;}
        else
        {
            long long p=Exeuclid(b,x,a%b,y,c);
            long long x_=x,y_=y;
            x=y_;y=x_-a/b*y_;
            return p;
        }
    }
    inline void china(void)
    {
        m_=1;
        for (int i=1;i<=n;i++)
            m_*=m[i];
        for (int i=1;i<=n;i++)
            M[i]=m_/m[i];
        for (int i=1;i<=n;i++)
        {
            long long y;
            Exeuclid(M[i],t[i],m[i],y,1);
            ans += a[i]%m_ * M[i]%m_ * t[i]%m_;
            ans %= m_;
        }
    }
    int main(void)
    {
        input();
        china();
        printf("%lld
    ",(ans%m_+m_)%m_);
        return 0;
    }
    

    拓展中国剩余定理

    对于形如

    [egin{cases} x equiv a_1(mod m_1) \ x equiv a_2(mod m_2) \ ... \ x equiv a_n(mod m_n) end{cases} ]

    这样的方程组,如果模数(m)两两互质,那么我们可以直接利用中国剩余定理构造出解。但是对于模数(m)不互质的情况,我们其实也可以利用类似的方法求解。

    我们考虑用数学归纳法的过程构造解。对于前(k-1)个方程,假设已经有一个合法的解(x),那么我们利用如下的方法得到满足前(k)个方程的解:

    (m=lcm(m_1,m_2,...,m_{k-1})),显然,对于(forall pin Z,x+pm)都是前(k-1)个方程的解。
    那么我们找一个(p=t),使得(x+pmequiv a_k(mod m_k))就是前(k)个方程的解了。这个就是扩展欧几里得算法的事了嘛。
    (x+pmequiv a_k(mod m_k)⇔pmequiv a_k-x(mod m_k)),扩展欧几里得解一下,如果无解,则原方程组无解。

    当然,求解最小整数解还是取模就行了。

    (Code:)

    inline long long ExCRT(void)
    {
        long long m_=m[1],x=r[1];
        for (int i=2;i<=n;i++)
        {
            long long x_,y_;
            if ( (r[i]-x) % gcd(m_,m[i]) )return -1;
            long long p=Exeuclid(m_,x_,m[i],y_,r[i]-x);
            long long Mod=m[i]/p;
            //要对当前的解先取模,防止爆longlong
            x_ = (x_%Mod+Mod)%Mod;
            x += x_ * m_;
            m_ = m_*m[i]/p;
            x = (x+m_)%m_;
        }
        return x;
    }
    

    <后记>

  • 相关阅读:
    Java 在方法和作用域内的内部类
    java 内部类和向上转型
    java 内部类使用 .this 和 .new
    java innerclasses(内部类)
    Java过滤器与SpringMVC拦截器之间的关系与区别
    Maven异常:Could not find artifact
    soapUI测试webservice(参数为xml格式的处理方式)
    maven仓库加载本地包依赖
    spring data jpa的学习总结
    Java 中常用缓存Cache机制的实现
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10685817.html
Copyright © 2020-2023  润新知