中国剩余定理(不互质的情况)-HDU3579

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;
}

你可能感兴趣的:(数学)