https://vjudge.net/problem/HDU-3579
套模板
先可以先找两个同余方程 设通解为N;
N=r1(mod(m1)),N=r2(mod(m2));
显然可以化为k1*m1+r1=k2*m2+r2;—>k1*m1+(-k2*m2)=r2-r1;
设a=m1,b=m2,x=k1,y=(-k2),c=r2-r1方程可写为ax+by=c;
由欧几里得解得x即可,那么将x化为原方程的最小正整数解,(x*(c/d)%(b/d)+(b/d))%(b/d);
这里看不懂的去看解模线性方程。那么这个x就是原方程的最小整数解。
所以N=a*(x+n*(b/d))+r1====N=(a*b/d)*n+(a*x+r1),
这里只有n为未知数所以又是一个N=(a*x+r1)(mod(a*b/d))的式子,
然后只要不断的将两个式变成一个式子,最后就能解出这个方程组的解。
#include
#include
#include
using namespace std;
const int maxn=100005;
const int inf=0x7fffffff;
typedef long long ll;
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)//扩展欧几里得
{
if(!b) {d=a;x=1;y=0;}
else{
ex_gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
ll ex_crt(ll *m,ll *r,int n)
{
ll M=m[1],R=r[1],x,y,d;
for(int i=2;i<=n;i++){
ex_gcd(M,m[i],d,x,y);
if((r[i]-R)%d) return -1;
x=(r[i]-R)/d*x%(m[i]/d);
R+=x*M;
M=M/d*m[i];
R%=M;
}
return R>0?R:R+M;
}
int main()
{
int t,n;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
scanf("%d",&n);
ll m[maxn],r[maxn];//m除数,r余数
for(int i=1;i<=n;i++) scanf("%lld",&m[i]);
for(int i=1;i<=n;i++) scanf("%lld",&r[i]);
printf("Case %d: %I64d\n",cas,ex_crt(m,r,n));
}
return 0;
}