强势看懂--中国剩余定理--不互质--解题模板

先上大佬代码:

#include<iostream>
#include<stdio.h>
using namespace std;
long long exgcd(long long a,long long b,long long &x,long long &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    long long q=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return q;
}
int main(){
    long long a1,c1,a2,c2,x,y,t;
    long long n;
    while(cin>>n){
        long long flag=1;
        cin>>a1>>c1;
        for(long long i=1;i<n;i++){
            cin>>a2>>c2;
            long long q=exgcd(a1,a2,x,y);
            if((c2-c1)%q!=0){
                flag=0;
            }
            t=a2/q;
            x=((x*(c2-c1)/q)%t+t)%t;
            //cout<<x;
            c1=c1+a1*x;
            a1=a1*(a2/q);
        }
        if(flag==0){
            cout<<"-1"<<endl;
            continue;
        }
        cout<<c1<<endl;
    }
    return 0;
}

造了一组数据:

n=6;

a[1]=5;a[2]=6;a[3]=7;a[4]=8;a[5]=9;a[6]=10;

c[1]=1;c[2]=2;c[3]=3;c[4]=4;c[5]=5;c[6]=6;

手写测试,写到崩溃,,

在代码上强势贴上牛皮*:

#include<iostream>
#include<stdio.h>
using namespace std;
long long exgcd(long long a,long long b,long long &x,long long &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    long long q=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return q;
}
int main(){
    long long a1,c1,a2,c2,x,y,t;
    long long n;
    while(cin>>n){
cout<<"  n="<<n<<endl;
        long long flag=1;
cout<<"  flag="<<flag<<endl;
        cin>>a1>>c1;
cout<<"  a1="<<a1<<"  c1="<<c1<<endl;
        for(long long i=1;i<n;i++){
cout<<"~~ i="<<i<<"  i<"<<n<<" ~~"<<endl;
            cin>>a2>>c2;
cout<<"  a2="<<a2<<"  c2="<<c2<<endl;
cout<<"  exgcd("<<a1<<","<<a2<<","<<x<<","<<y<<")"<<endl;
            long long q=exgcd(a1,a2,x,y);
cout<<"  q="<<q<<"=exgcd()"<<endl;
cout<<"  (c2-c1)%"<<q<<"="<<(c2-c1)%q<<endl;
            if((c2-c1)%q!=0){
                flag=0;
            }
            t=a2/q;
cout<<"  t="<<a2<<"/"<<q<<"="<<t<<endl;
cout<<"  x=(("<<x<<"*("<<c2<<"-"<<c1<<")/"<<q<<")%"<<t<<"+"<<t<<")%"<<t<<"="<<((x*(c2-c1)/q)%t+t)%t<<endl;
            x=((x*(c2-c1)/q)%t+t)%t;
cout<<"  c1="<<c1<<"+"<<a1<<"*"<<x<<"="<<c1+a1*x<<endl;
            c1=c1+a1*x;
cout<<"  a1="<<a1<<"*("<<a2<<"/"<<q<<")="<<a1*(a2/q)<<endl;
            a1=a1*(a2/q);
        }
        if(flag==0){
            cout<<"-1"<<endl;
            continue;
        }
        cout<<c1<<endl;
    }
    return 0;
}

输出结果如下:

 

 虽然不不明白那些式子是怎么推出来的,但是可以看明白其代表的意思:

先取出前两组,让c1保存前两组的解,a1保存余数为c1的除数,将前两组看成一个整体,再与第三组求解,这样

c1保存前三组的解,a1保存余数为的除数,前三组看做一个整体,,,如果有条件不满足,即不满足欧几里得游街的充分必要条件时,flag变为0,无解,否则到最后一步,c1保存的即是全部同余式的解。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值