<更新提示>

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



<正文>

编程实现解一次同余方程java 一次同余方程的解法_编程实现解一次同余方程java


同余方程(NOIP2012)

Description

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

Input Format

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

Output Format

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

Sample Input

3 10

Sample Output

7

解析

模板题,将方程化为\(ax+by=1\),用扩展欧几里得算法求解。由于数据保证\(b\geq2\),所以不存在\(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\n",(X%(B/p)+(B/p))%(B/p));
	return 0;
}

编程实现解一次同余方程java 一次同余方程的解法_取模_02

曹冲养猪

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\n",(ans%m_+m_)%m_);
    return 0;
}

编程实现解一次同余方程java 一次同余方程的解法_取模_03

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;
}

<后记>