解题思路:这道题目有可能a[i],两两不互质,所以直接用中国剩余定理肯定是不对的。。这里考虑非互质的情况
问题描述:给出bi,ni的值,且n1, n2, n3,…, ni两两之间不一定互质,求Res的值?
解:采用的是合并方程的做法。
这里将以合并第一第二个方程为例进行说明
由上图前2个方程得(设k1、k2为某一整数):
这里实际上是利用了一种迭代的思想,前两个方程合并成一个新的模方程,然后再与第三个合并.......,一直到最后一个方程,最后可以求出解来。。注意这里为了求出最小非负整数解,采用了很多技巧。。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int gcd(int a,int b,int &x,int &y)
{
if(a == 0 && b == 0) return -1;
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int d = gcd(b,a%b,y,x);
y -= a/b*x;
return d;
}
int main()
{
int n,m,t,m1,m2,r1,r2,flag;
int a[11],b[11];
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i = 0; i < m; i++)
cin>>a[i];
for(int i = 0; i < m; i++)
cin>>b[i];
flag = 0; m1 = a[0]; r1 = b[0];
for(int i = 1; i < m; i++)
{
int x,y;
m2 = a[i]; r2 = b[i];
int d = gcd(m1,m2,x,y);
int c = r2-r1;
if(c % d)
{
flag = 1;
break;
}
int tmp = m2 / d;
x = (c / d * x % tmp + tmp) % tmp;
r1 = r1 + x * m1;
m1 = m1 / d * m2;
}
if(flag || n < r1)
cout<<0<<endl;
else
{
int ans = (n - r1) / m1 + 1; //m1为ai的最小公倍数,凡是m1*i+r1的都是符合要求的数,其中r1最小
if(r1 == 0) ans--; //要求是正整数
cout<<ans<<endl;
}
}
return 0;
}