zoukankan      html  css  js  c++  java
  • HDU 1573 模线性方程

    给定模线性方程组,求最终的值的通解。点击

    两个模方程可以化解成一个模方程

    x mod a1 = b1

    x mod a2 = b2

    a1*k1 + a2*k2 = b2 – b1 // 其中k1k2是自由元

    用扩展欧几里得算出k1的解,当然它是一个解系,找出最小k1作为特解,带入x = a1 * k1 + b1得到x

    然后把这个x当作特解,记作x1.

    之前k1本来是一个解系,他的模是a2/gcd(a1,a2),[简单将gcd(a1,a2)记作t], 也就是说k1如果作为一个解系的话,k1 = a2/t * x + k0

    其中x是任意整数,k0是一个特解。

    将求到的k1代入到x = a1 * k1 + b1 中,得到的是一个x的解系,如果用上边的特解x0表示,就是x = x0 + a1*a2/t;

    得到一个新的模方程 x mod a1*a2/t = x0 ,这个方程继承上面两个方程的特性,所以两者之间是等价的。

    这样将两个两个方程消掉,最后只剩下一个方程,最后的解系就是最终的x的解系。如果中间出现欧几里得算不出来解,那么说明这个方程组没有解。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    typedef long long LL;
    const int N = 1e6 + 500;
    
    void extend_gcd(LL a, LL b, LL &x, LL &y, LL &d)
    {
        if(b == 0)
        {
            x = 1;
            y = 0;
            d = a;
        }
        else
        {
            extend_gcd(b, a%b, y, x, d);
            y -= (a/b) * x;
        }
    }
    int T,n,m;
    LL a[20],b[20];
    
    int main()
    {
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d", &n, &m);
            for(int i = 0; i < m; i++)
                scanf("%d", &a[i]);
            for(int j = 0; j < m; j++)
                scanf("%d", &b[j]);
    
            LL flag = 0;
            LL x, y, d;
            LL m1 = a[0], r1 = b[0];
            LL m2, r2;
            LL c, t;
            for(int i = 1; i < m; i++)
            {
                m2 = a[i], r2 = b[i];
                extend_gcd(m1, m2, x, y, d);//d = gcd(m1,m2)  m1*x + m2*y = gcd(m1,m2)
                c = r2 - r1;
                if(c % d)
                {
                    flag = 1;
                    break;
                }
    
                t = m2 / d; // m1*(x+m2/d*k1) + m2*(y + m1/d*k2) = m1*x + m2*y + (m1*m2/d * k1 + m2*m1/d*k2) = gcd(m1,m2)
                x = (((x * c / d) % t) + t) % t;
    
                r1 = m1*x + r1;
                m1 = m1*m2/d;
                r1 %= m1;
            }
            int ans = 0;
            if(flag || r1 > n)
            {
                printf("0
    ");
            }
            else
            {
                int ans = (n - r1) / m1 + 1;
                if(r1 == 0) ans--;
                printf("%d
    ", ans);
            }
    
        }
    
        return 0;
    
    }
    如果有错误,请指出,谢谢
  • 相关阅读:
    linux 安装ssh
    Pwn环境安装
    18年最后一天
    绘制分形树
    python之绘制图形库turtle(转)
    turtle绘制多个五角星
    Flask的基本操作知识
    pycharm-professional-2018.2.3 汉化激活安装过程
    Could not find a version that satisfies the requirement flask
    豆瓣即将上映电影爬虫作业
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7226539.html
Copyright © 2011-2022 走看看