ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1018 一个小问题 扩展中国剩余定理

2022-07-28 03:31:10  阅读:88  来源: 互联网

标签:剩余 int 定理 a1 k1 a2 1018 m2 m1


链接:https://ac.nowcoder.com/acm/problem/15068
来源:牛客网

题目描述

uu遇到了一个小问题,可是他不想答。你能替他解决这个问题吗?
问题:给你k对a和r是否存在一个正整数x使每队a和r都满足:x mod a=r,求最小正解x或无解。

输入描述:

第一行是正整数k(k<=100000)
接下来k行,每行有俩个正整数a,r(100000>a>r>=0)

输出描述:

在每个测试用例输出非负整数m,占一行。
如果有多个可能的值,输出最小的值。
如果没有可能的值,则输出-1。
示例1

输入

复制
2
8 7
11 9

输出

复制
31

分析

由于模数不互质,所以要用扩展中国剩余定理。

要注意让(m2 - m1) / d,让k1 / d可能会损失

思想:

由前两项得到方程:

x = k1 * a1 + m1;

x = k2 * a2 + m2;

消去x 得到方程:k1 * a1 - k2 * a2 = (m2 - m1)

通过扩展欧几里得算出:k1' * a1 - k2' * a2 = (a1,a2)

进而算出k1 = k1' * a2 / (a1,a2) ;

构造新的 x = k1 * a1 + m1

x=(k1+k∗a2/d)∗a1+m1x
=k1∗a1+m1+k∗a2∗a1/d
=k1∗a1+m1+k∗lcm(a1,a2)

等价替换得到:

新的a1 = abs(lcm(a1,a2))

新的m1 = k1 * a1 + m1; 

int k;

#define int long long

int exgcd(int a,int b,int& x,int& y) {
    if(!b) { x = 1,y = 0; return a; } 
    int d = exgcd(b,a%b,y,x);
    y = y - a / b * x;
    return d;
}

inline int mod(int a,int b) {
    return (a % b + b) % b;
}

int EXCRT() {
    int a1,m1;
    cin>>a1>>m1;
    fo(i,2,k) {
        int a2,m2;cin>>a2>>m2;
        int k1,k2,d = exgcd(a1,-a2,k1,k2);
        if((m2 - m1) % d) {return -1;}
        k1 = mod(k1 * (m2 - m1) / d,abs(a2 / d));//要注意让(m2 - m1) / d,让k1 / d可能会损失
        
        m1 = k1 * a1 + m1;
        
        a1 = abs(a1 / d * a2);
    }
    return mod(m1,a1);
}

signed main() {
    cin>>k;
    
    cout<<CRT()<<endl;
}

 

标签:剩余,int,定理,a1,k1,a2,1018,m2,m1
来源: https://www.cnblogs.com/er007/p/16527147.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有