zoukankan      html  css  js  c++  java
  • AcWing 204. 表达整数的奇怪方式

    题目传送门

    1、将式子等价转换

    考虑前两个式子:

    (x≡m_1(\% a_1))

    (x≡m_2(\% a_2))

    变形:

    (x=k_1∗a_1+m_1)

    (x=k_2∗a_2+m_2)

    联立消掉(x),得到:

    (k_1∗a_1+m_1=k_2∗a_2+m_2)

    移项:

    (k_1∗a_1−k_2∗a_2=m_2−m_1)

    也就是:

    (① k_1∗a_1+k_2∗(−a_2)=m_2−m_1)

    本题预求:一个最小的非负整数(x)

    因为要求(x)最小,而(a_i)(m_i)都是正数,也就是需要找到一个最小的(k_1,k_2),使得等式成立。

    那么如何找到(k_1,k_2)的最小解呢?方程(①)其实就是形如(ax+by=c)的一个不定方程,可以考虑使用扩展欧几里得来求最小解。

    扩展欧几里得来求最小解的步骤:

    1. 利用扩展欧几里得计算出方程(ax+by=gcd(a,b))的一组解(x_0,y_0)

    2. 通过变换公式得到(ax+by=c)的特解(x_1=x_0∗c/d, y_1=y_0∗c/d;)

    3. 最小解:(int s=b/d; x_{min}=(x_1\%s+s)\%s);

    2. 用扩展欧几里得算法找出一组解

    已知(a_1,m_1,a_2,m_2),可以用扩展欧几里得算法算出一个(k′_1,k′_2)使得:

    (② k′_1∗a_1+k′_2∗(−a_2)=gcd(a_1,−a_2)) 【这是在计算(ax+by=gcd(a,b))的一组解】


    无解判断
    (gcd(a_1,−a_2)∤(m_2−m_1)),则无解,返回即可。


    如果有解
    (d=gcd(a_1,−a_2),y=frac{m_2−m_1}{d})

    连立(①)式和(②)式:
    我们只需要将(k′_1)(k′_2)分别扩大(y)倍,则可以以找出一个(k_1,k_2)满足(①)式:
    (k_1=k′_1∗y,k_2=k′_2∗y) 【这是在求(ax+by=c)的特解】

    3. 找到最小正整数解

    有了(ax+by=c)的特解,就可以来求方程的通解和最小解了。

    我们知道一个性质:

    (③ k_1=k_1+k∗frac{a_2}{d})
    ( k_2=k_2+k∗frac{a_1}{d})

    (k)为任意整数,这时新的(k_1,k_2)仍满足(①)式。


    性质证明:
    将新的(k_1,k_2)带入式子(k_1∗a_1−k_2∗a_2=m_2−m_1)得:

    ((k_1+k∗frac{a_2}{d})∗a_1+(k_2+k∗frac{a_1}{d})∗(−a_2)=m_2−m_1)

    拆出来:

    (k_1∗a_1+k∗frac{a_2∗a_1}{d}+k_2∗(−a_2)+k∗frac{a_1∗(−a_2)}{d}=m_2−m_1)

    交换一下顺序,把负号拆出来:

    (k_1∗a_1+k_2∗(−a_2)+k∗frac{a_2∗a_1}{d}−k∗frac{a_1∗a_2}{d}=m_2−m_1)

    那个同加同减可以消掉:

    (k_1∗a_1+k_2∗(−a_2)=m_2−m_1)

    这个式子和(①)是一样的,因(①)成立,故此式也成立。


    有了上面的性质,要找一个最小的非负整数解,我们只需要让

    (k_1=k_1 \%  abs(frac{a_2}{d}))

    (k_2=k_2 \%  abs(frac{a_1}{d}))

    就是在(k_1)中尽可能的去掉(abs (frac{a_2}{d})),就可找到当前最小的(k_1,k_2)的解,也就是不断的减小(k)的值,直至(k)(0),简单点来说是,就是一步模完。

    (Q):此处为什么要取绝对值呢?

    (A):因为不知道(frac{a_2}{d})的正负性,我们在原基础上要尽量减多个(abs(frac{a_2}{d})),使其为正整数且最小。

    4. 等效替代

    (②)式带入(x=k_1∗a_1+m_1)

    则:

    (x=(k_1+k∗frac{a_2}{d})∗a_1+m_1)

    (=k_1∗a_1+m_1+k∗frac{a_2∗a_1}{d})

    (=k_1∗a_1+m_1+k∗lcm(a_1,a_2))

    (Q):这里,(k)都为(0)了,为什么还要算呢?

    (A):因为这只是前两个式子得最小(k),有可能遇到下一个式子后面被迫要扩大

    (③)中,我们设(a_0=lcm(a_1,a_2)),(m_0=k_1∗a_1+m_1) 【之所以这样设,是因为(a_1,a_2,k_1,m_1)都是已知数,可以算出来,未知的是(x,k)
    那么:

    (③ =k∗a_0+m_0)

    这个形式与一开始我们分解的形式是不是特别像呢?

    没错!假设之后又来了一个(a3,m3)

    我们只需要继续找:

    (x=k∗a_0+m_0=k_3∗(−a_3)+m_3),那么问题又回到了第一步。

    5.总结

    我们的做法相当于每次考虑合并两个式子,将这(n)个式子合并(n−1)次后变为一个式子。最后剩下的式子就满足我们的答案。

    注意:

    1. (lcm(a_1,a_2))(\%frac{a_2}{d}),需要取绝对值。又因为(d=gcd(a_1,−a_2)),我们不知道(a_1)的正负性(可能是上一步推过来的)。

    2. (\%frac{a_2}{d}),需要取绝对值, 模负数的话,不会取到正解;

    6、完整代码

    #include <iostream>
    
    using namespace std;
    typedef long long LL;
    
    LL exgcd(LL a, LL b, LL &x, LL &y) {
        if (!b) {
            x = 1, y = 0;
            return a;
        }
        LL d = exgcd(b, a % b, y, x);
        y -= a / b * x;
        return d;
    }
    
    int main() {
        int n;
        cin >> n;
    
        //先读入第一个方程
        LL a1, m1;
        cin >> a1 >> m1;
    
        //依次读入n-1个方程,每次合并一个方程
        for (int i = 0; i < n - 1; i++) {
            LL a2, m2;
            cin >> a2 >> m2;
            //开始合并
            LL k1, k2;
            //a1*k1+(-a2)*k2=m2-m1
            LL d = exgcd(a1, -a2, k1, k2);
            if ((m2 - m1) % d) { //如果不是0,则无解
                cout << -1;
                exit(0);
            }
            //求 ax+by=c的特解
            k1 *= (m2 - m1) / d;
    
            //使得k1成为方程的最小正整数解
            int t = abs(a2 / d);
            k1 = (k1 % t + t) % t;
    
            //需要更新a1和m1了
            m1 = k1 * a1 + m1;
            a1 = abs(a1 / d * a2);
        }
        cout << (m1 % a1 + a1) % a1;
        return 0;
    }
    
  • 相关阅读:
    tp5 引入 没有命名空间的类库的方法(以微信支付SDK为例)
    VMware虚拟机安装黑苹果MacOS Mojave系统详细教程
    本文实例讲述了PHP7基于curl实现的上传图片功能-formdata格式上传图片
    宝板面板无法安装,宝塔无法更新安装插件,比如无法安装ftp插件,通过更换hosts指向就可以了
    destoon GBK版本dhtmlspecialchars函数 bug
    有以下40个迹象表明你还是PHP菜鸟
    对高访问量与庞大数据处理的网站系统结构分析
    加入收藏与设为首页JS兼容简易效果
    html让没有宽高限制的图片居中
    PHP识别url重写请求
  • 原文地址:https://www.cnblogs.com/littlehb/p/15379880.html
Copyright © 2011-2022 走看看