中国剩余定理模板(1) 两两互质情况

来源:互联网 发布:windows 远程连接 mac 编辑:程序博客网 时间:2024/06/15 19:59

两两互质的情况....如果不互质的话,那么就成了解线性模余方程了..

先看神牛的吧,我的代码好乱,主函数的输入有些不一样

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
typedef __int64 int64;  
int64 a[15],b[15];  
 
int64 Extend_Euclid(int64 a, int64 b, int64&x, int64& y)  
{  
    if(b==0)  
    {  
        x=1,y=0;  
        return a;  
    }  
    int64 d = Extend_Euclid(b,a%b,x,y);  
    int64 t = x;  
    x = y;  
    y = t - a/b*y;  
    return d;  
}  
//求解模线性方程组x=ai(mod ni)  
int64 China_Reminder(int len, int64* a, int64* n)  
{  
    int i;  
    int64 N = 1;  
    int64 result = 0;  
    for(i = 0; i < len; i++)  
        N = N*n[i];  
    for(i = 0; i < len; i++)  
    {  
        int64 m = N/n[i];  
        int64 x,y;  
        Extend_Euclid(m,n[i],x,y);  
        x = (x%n[i]+n[i])%n[i];  
        result = (result + m*a[i]*x%N)%N;  
    }  
    return result;  
}  

int main()  
{  
    int n;  
    while(scanf("%d",&n)!=EOF)  
    {  
        for(int i = 0; i < n; i++)  
            scanf("%I64d %I64d",&a[i],&b[i]);  
        printf("%I64d\n",China_Reminder(n,b,a));  
    }  
    return 0;  

 

在没有看模板之前,我是纯按照孙子定理表格的计算来的写的,很丑...

 

// a[]除数,b[ ]余数,c[ ] mod a[ ]后的衍数,d[ ] mod lcm的衍数
// sum[]乘率也是逆元 ,tall总和
#include<iostream>
#include<cmath>
using namespace std;

int gcd(int a,int b){
    if(b==0) return a;
    return gcd(b,a%b);
}

int Ext_gcd(int a,int b,int &x,int &y){
    if(b==0) { x=1, y=0; return a; }
    int d= Ext_gcd(b,a%b,y,x);
    y-= a/b*x;
    return d;
}   
int Inv(int a,int m){
    int d,x,y;
    d= Ext_gcd(a,(int)m,x,y);
    if(d==1) return (x%m+m)%m;
    return -1;
}   

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int m,lcm=1;
        scanf("%d",&m);
        int a[12],b[12],c[12],d[12],sum[12],tall=0;
        for(int i=0;i<=11;i++)
            c[i]=1,d[i]=1;
        for(int i=1;i<=m;i++){
            scanf("%d",&a[i]);
            lcm=a[i]*lcm/gcd(lcm,a[i]); //// 求最小公倍数
        }   
        for(int i=1;i<=m;i++)
            scanf("%d",&b[i]);
        for(int i=1;i<=m;i++){
            for(int j=1;j<=m;j++){
                if(j!=i){
                    c[i] = a[j]%a[i] *(c[i]%a[i])%a[i];
                    d[i] = a[j] * d[i]%lcm;
                }
            }
        }
       
        for(int i=1;i<=m;i++){
            sum[i] = Inv(c[i],a[i]);  //// 求乘率也就是逆元
            tall = tall%lcm + sum[i]*d[i]*b[i]%lcm;  //// 求出最小的符合条件答数
        }
        if(tall>lcm) tall %= lcm;   //// 求出最小的符合条件答数
        printf("%d\n",tall);
    }
}

 

 

原创粉丝点击