码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1573 模线性方程

时间:2017-07-24 00:11:48      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:bre   ++   net   else   space   class   lan   details   stdio.h   

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

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

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\n");
        }
        else
        {
            int ans = (n - r1) / m1 + 1;
            if(r1 == 0) ans--;
            printf("%d\n", ans);
        }

    }

    return 0;

}

HDU 1573 模线性方程

标签:bre   ++   net   else   space   class   lan   details   stdio.h   

原文地址:http://www.cnblogs.com/Alruddy/p/7226539.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!