zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    c语言,动态数组
    利用Word来发布博客到博客园(onenote类似)
    c语言,volatile
    c语言,变长数组
    C语言,sprintf与sscanf函数[总结]
    c语言,数组和指针
    Linux的notifier机制的应用
    Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)
    内核线程的进程描述符task_struct中的mm和active_mm
    Linux用户抢占和内核抢占详解(概念, 实现和触发时机)--Linux进程的管理与调度(二十)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7891141.html
Copyright © 2011-2022 走看看