题干:求在小于等于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)。中文题。
题目思路:裸的中国剩余定理,可以练练手。
先从两个式子入手:x+a[0]*k1=b[0];
x+a[1]*k2=b[1]; 由以上两式子可以得出:a[1]*k2-a[0]*k1=b[1]-b[0];
用扩展欧几里得可以解出上述式子,之后类推即可。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#define Memset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1010;
#define LL long long
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
LL ex_gcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
LL ans=ex_gcd(b,a%b,x,y);
LL tmp=x;
x=y;
y=tmp-a/b*y;
return ans;
}
LL modeqset(LL a[],LL b[],LL n)
{
LL i,d,c,x,y,t;
for(i=1;i<n;i++)
{
c=b[i]-b[i-1];
d=ex_gcd(a[i-1],a[i],x,y);
if(c%d) return -1;
t=a[i]/d;
x=(x*(c/d)%t+t)%t; //解决x的负数情况,因为x+kt是式子的解,所以((x+kt)%t+t)%t)也必定是式子的正数解;
b[i]=x*a[i-1]+b[i-1];
a[i]=a[i-1]*(a[i]/d); //以前面的解推出后面系数,依此类推。
}
return b[n-1];
}
int main()
{
LL a[30],b[30],m,tmp,flag,i,n,lcm=1,num;
int t;
scanf("%d",&t);
while(t--)
{
lcm=1;
scanf("%lld%lld",&n,&m);
for(i=0;i<m;i++)
{
scanf("%lld",&a[i]);
lcm=lcm/(gcd(lcm,a[i]))*a[i]; //求出a[i]的最大公倍数;
}
for(i=0;i<m;i++)
scanf("%lld",&b[i]);
LL res=modeqset(a,b,m);
if(res==-1|| res>n)
printf("0\n");
else
{
num=(n-res)/lcm+1; //n和解的最小值相减,之后除以最大公倍数,加上原本的res;
if(res==0)
num--; //若res=0,就多加了1,减去即可。
printf("%lld\n",num);
}
}
return 0;
}