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
分析:非互质版中国剩余定理.先求出最小正整数解,然后求出所有模数的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; }