您的位置:首页 > 其它

Hdu1573 X问题

2017-11-24 16:15 155 查看

X问题

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


[align=left]Problem Description[/align]
求在小于等于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)。

[align=left]Input[/align]
输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为两个正整数N,M (0 < N <= 1000,000,000 , 0 < M <= 10),表示X小于等于N,数组a和b中各有M个元素。接下来两行,每行各有M个正整数,分别为a和b中的元素。

[align=left]Output[/align]
对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。

[align=left]Sample Input[/align]

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

[align=left]Sample Output[/align]

1
0
3

[align=left]Author[/align]
lwg

[align=left]Source[/align]
HDU 2007-1 Programming Contest

[align=left]Recommend[/align]
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: