【hihocoder 1303】模线性方程组

【题目链接】:http://hihocoder.com/problemset/problem/1303

【题意】

【题解】

/*
    x % m[1] = r[1]
    x % m[2] = r[2]

    x = k[1]*m[1]+r[1]  ···①
    x = k[2]*m[2]+r[2]  ···②

    k[1]*m[1]+r[1]=k[2]*m[2]+r[2]
    m[1]*k[1]-m[2]*k[2]=r[2]-r[1]
    令A=m[1],B=m[2],C=r[2]-r[1],x=k[1],y = -k[2];
    A*x+B*y=C
    令t = gcd(A,B)
    如果C%t!=0则无解
    令A'=A/t,B'=B/t,C'=C/t
    A'*x+B'y=C'

    对于A'x+B‘y=1
    求出x0,然后乘上C;
    就是A'x+B'y=C'的一个特解了
    x0 = x0*C;
    然后这个时候x0可能为负值吧;
    所以求最小的正值;
    x0 = (x0%B'+B')%B';
    就能算出来k[1],也即k[1]=x0,;
    带回①式
    x0= x0*m[1]+r[1]
    将x0作为特解;
    得到一个解系
    x = x0+t*lcm(m[1],m[2]);
    这样就相当于得到一个新的方程
    X % lcm(m[1],m[2]) == x0

    令M = lcm(m[1], m[2]), R = x0,则有新的模方程X mod M = R。
    此时,可以发现我们将x mod m[1] = r[1],x mod m[2] = r[2]
    合并为了一个式子X mod lcm(m[1], m[2]) = x。满足后者的X一定
    满足前两个式子。

    这里x0也取最小的正值吧
        x0 = x0%lcm(m[1],m[2]);
        if (x0<lcm(m[1],m[2])) x0+=lcm(m[1],m[2]);

    如果再有一个方程
    X % m[3] = r[3]
    则可以再用相同的方法求出它的解系
    最后输出那个x0就好了
*/


【Number Of WA

2

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 110;

int n;
LL m1,r1,m2,r2;

LL gcd(LL a,LL b)
{
    if (b==0)
        return a;
    else
        return gcd(b,a%b);
}

void ex_gcd(LL a,LL b,LL &x,LL &y)
{
    if (b==0)
    {
        x = 1,y = 0;
        return;
    }
    ex_gcd(b,a%b,y,x);
    y-=a/b*x;
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf not use
    cin >> n;
    cin >> m1 >> r1;
    rep1(i,2,n)
    {
        cin >> m2 >> r2;

        LL A = m1,B = m2,C = r2-r1;
        LL t = gcd(m1,m2);

        if (C%t!=0) return cout << -1 << endl,0;

        A/=t,B/=t,C/=t;

        LL x0,temp;
        ex_gcd(A,B,x0,temp);
        x0=(C*x0%B+B)%B;//求出A'x+B'y=C'的最小的正值特解

        x0 = x0*m1+r1;//x0=k[1],回带出模线性方程组的特解

        LL lcm = m1/t*m2;
        x0 = x0%lcm;
        if (x0<0) x0+=lcm;//求出特解里面的最小正值

        m1 = lcm,r1 = x0;

        if (i==n) cout << x0 << endl;
    }
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(115)  评论(0编辑  收藏  举报