• poj 2891 Strange Way to Express Integers (求解线性同余方程组/模板)


    题意:给你n个对数,ai,ki

    X = a1 *x1 + k1

    X = a2 *x2 + k2

    .....

    X = ai*xi  + ki

    问你是否存在这样一个X,存在就输出该值,否则输出-1

    思路:

    对于模线性方程组,可以进行方程组合并,求出合并后的方程的解,这样就可以很快的推出方程的最终解,不管这样的方程有多少个,都可以俩俩解决,求得方程组的最终解。

    x=b1(mod m1) (1);

    x=b2(mod m2) (2);

     

    m=lcm(m1,m2). 

     

    首先,此次方程组有解的充分必要条件是gcd(m1,m2)|gcd(b1,b2),此时方程仅有一个小于m 的非负整数解,利用扩展欧几里德算法解出来。 

    式(1)等价于x=b1+m1*y1;

    式(2)等价于x=b2+m2*y2;

    联立可得b1+m2*y1=b2+m2*y2,即m2*y2-m1*y1=b1-b2;  

    根据之前所学模线性方程的方法,很容易得到此方程的解有y2,因此小于m的非负整数解即为(b2+m2*y2)%m。

    明显这是其中一组解,y2+K*lcm(m1,m2)都是解(每次加上最小公倍数)。(k=0,1,2,3。。。)

    代码:

    #include <iostream>
    #include <cstdio>
    #define ll long long 
    
    using namespace std;
    
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return a;
        }
        ll d=exgcd(b,a%b,x,y);
        ll t=x;
        x=y;
        y=t-a/b*y;
        return d;
    }
    
    ll solve(ll a[],ll r[],ll n)
    {
        ll d,c,i,x,y,t;
        for(i=1;i<n;i++)
        {
            c=r[i]-r[i-1];
            d=exgcd(a[i-1],a[i],x,y);
            if(c%d!=0) return -1;
            t=a[i]/d;
            x=(x*(c/d)%t+t)%t;
            r[i]=a[i-1]*x+r[i-1];
            a[i]=a[i-1]*(a[i]/d);
        }
        return r[n-1];
    }
    
    int main() {
        ll n;
        ll a[100005];
        ll r[100005];
        while(cin>>n)
        {
            for(int i=0;i<n;i++)
            scanf("%lld %lld",&a[i],&r[i]);
            ll ans=solve(a,r,n);
            cout<<ans<<endl;
        }
        return 0;
    }

     

  • 相关阅读:
    JS面向对象的程序设计
    dede 调用自定义图片时新增了很多html结构的解决方法
    dedecms arclist 栏目文章列表调用标签
    POJ 3145 Harmony Forever
    URAL K-based Numbers(1-3)
    POj 3420
    Ural 1004 FLOYD最小环问题
    noip2016提高组总结
    POJ 2566 Bound Found
    POJ 1639度限制生成树
  • 原文地址:https://www.cnblogs.com/simplekinght/p/6817834.html
Copyright © 2020-2023  润新知