点击打开题目
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5167 Accepted Submission(s): 1732
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
HDU 2007-1 Programming Contest
中国剩余定理求1~N有多少个满足条件的数。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MAX 10
__int64 a[MAX+11];
__int64 m[MAX+11];
__int64 lcm;
__int64 GCD(__int64 a , __int64 b)
{
return b == 0 ? a : GCD(b,a%b);
}
__int64 exGCD(__int64 a,__int64 b,__int64 &x,__int64 &y)
{
if (!b)
{
x = 1;
y = 0;
return a;
}
int g = exGCD(b,a%b,y,x);
y -= a / b * x;
return g;
}
__int64 CRT(__int64 *m,__int64 *a,int n) //x % m == a
{
lcm = 1;
for (int i = 1 ; i <= n ; i++)
lcm = m[i] / GCD(m[i],lcm) * lcm;
for (int i = 2 ; i <= n ; i++)
{
__int64 A = m[1] , B = m[i],d,x,y,c = a[i] - a[1]; //d 为 GCD(A,B)
d = exGCD(A,B,x,y);
if (c % d != 0) //无解
return -1;
__int64 mod = m[i] / d;
//然后套公式
__int64 K = ((x * c / d) % mod + mod) % mod;
a[1] = m[1] * K + a[1];
m[1] = m[1] * m[i] / d;
}
if (a[1] == 0) //如果最后合并的结果的余数为0,答案就是他们的最小公倍数
return lcm;
return a[1];
}
int main()
{
int n;
int u;
__int64 k;
scanf ("%d",&u);
while (u--)
{
scanf ("%I64d %d",&k,&n);
for (int i = 1 ; i <= n ; i++)
scanf ("%I64d",&m[i]);
for (int i = 1 ; i <= n ; i++)
scanf ("%I64d",&a[i]);
__int64 ans = CRT(m,a,n);
if (ans == -1)
printf ("0\n");
else if (ans <= k)
printf ("%I64d\n",(k - ans) / lcm + 1);
else
printf ("0\n");
}
return 0;
}