Hdu1573 X问题

X问题

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7081    Accepted Submission(s): 2493


Problem Description
求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], …, X mod a[i] = b[i], … (0 < a[i] <= 10)。
 
Input
输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为两个正整数N,M (0 < N <= 1000,000,000 , 0 < M <= 10),表示X小于等于N,数组a和b中各有M个元素。接下来两行,每行各有M个正整数,分别为a和b中的元素。
 
Output
对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。
 
Sample Input
3 10 3 1 2 3 0 1 2 100 7 3 4 5 6 7 8 9 1 2 3 4 5 6 7 10000 10 1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5 6 7 8 9
 
Sample Output
1 0 3
 
Author
lwg
 
Source
 
Recommend
linle   |   We have carefully selected several similar problems for you:  1788 1695 1452 1060 1299 
分析:非互质版中国剩余定理.先求出最小正整数解,然后求出所有模数的lcm,那么解x' = x+k*lcm.统计一下个数就可以了.非常坑的一点是方程可以解出来0,也就是说如果一开始的解是0,那么就要加上lcm变成正整数解.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
ll a[1010], b[1010], n, T, m, lcm, ans;

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

ll niyuan(ll x, ll mod)
{
    ll px, py, t;
    t = exgcd(x, mod, px, py);
    if (t != 1)
        return -1;
    return (px % mod + mod) % mod;
}

ll gcd(ll a, ll b)
{
    if (!b)
        return a;
    return gcd(b, a%b);
}

bool hebing(ll a1, ll b1, ll a2, ll b2, ll &a3, ll &b3)
{
    ll d = gcd(b1, b2), c = a2 - a1;
    if (c % d != 0)
        return false;
    c = (c % b2 + b2) % b2;
    b1 /= d;
    b2 /= d;
    c /= d;
    c *= niyuan(b1, b2);
    c %= b2;
    c *= b1 * d;
    c += a1;
    b3 = b1 * b2 * d;
    a3 = (c % b3 + b3) % b3;
    return true;
}

ll China()
{
    ll a1 = a[1], a2, a3, b1 = b[1], b2, b3;
    for (ll i = 2; i <= m; i++)
    {
        a2 = a[i], b2 = b[i];
        if (!hebing(a1, b1, a2, b2, a3, b3))
            return -1;
        a1 = a3;
        b1 = b3;
    }
    return (a1 % b1 + b1) % b1;
}

int main()
{
    scanf("%lld", &T);
    while (T--)
    {
        lcm = 0;
        cin >> n >> m;
        for (ll i = 1; i <= m; i++)
        {
            cin >> b[i];
            if (i == 1)
                lcm = b[i];
            else
                lcm = lcm / gcd(lcm, b[i]) * b[i];
        }
        for (ll i = 1; i <= m; i++)
            cin >> a[i];
        ll temp = China();
        if (temp != -1)
        {
            while (temp <= 0)
                temp += lcm;
        }
        if (temp == -1 || temp > n)
            cout << 0 << endl;
        else
            cout << (n - temp) / lcm + 1 << endl;
    }

    return 0;
}
posted @ 2017-11-24 16:15  zbtrs  阅读(284)  评论(0编辑  收藏  举报