HDU, 3579 Hello Kiki

题意:……中国剩余定理非互质版

思路:中国剩余定理非互质版

  PS:注意只有一个数且余数为0时特判

= =关于互质版中国剩余定理直接copy了模版

剩余定理互质版模版来源:

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 typedef __int64 int64;
  6 int64 Mod;
  7 int64 a[1000],b[1000];
  8 int64 gcd(int64 a, int64 b)
  9 {
 10     if(b==0)
 11         return a;
 12     return gcd(b,a%b);
 13 }
 14 
 15 int64 Extend_Euclid(int64 a, int64 b, int64&x, int64& y)
 16 {
 17     if(b==0)
 18     {
 19         x=1,y=0;
 20         return a;
 21     }
 22     int64 d = Extend_Euclid(b,a%b,x,y);
 23     int64 t = x;
 24     x = y;
 25     y = t - a/b*y;
 26     return d;
 27 }
 28 
 29 //a在模n乘法下的逆元,没有则返回-1
 30 int64 inv(int64 a, int64 n)
 31 {
 32     int64 x,y;
 33     int64 t = Extend_Euclid(a,n,x,y);
 34     if(t != 1)
 35         return -1;
 36     return (x%n+n)%n;
 37 }
 38 
 39 //将两个方程合并为一个
 40 bool merge(int64 a1, int64 n1, int64 a2, int64 n2, int64& a3, int64& n3)
 41 {
 42     int64 d = gcd(n1,n2);
 43     int64 c = a2-a1;
 44     if(c%d)
 45         return false;
 46     c = (c%n2+n2)%n2;
 47     c /= d;
 48     n1 /= d;
 49     n2 /= d;
 50     c *= inv(n1,n2);
 51     c %= n2;
 52     c *= n1*d;
 53     c += a1;
 54     n3 = n1*n2*d;
 55     a3 = (c%n3+n3)%n3;
 56     return true;
 57 }
 58 int64 Chinese_Remainder (int64 b[],int64 a[],int len)
 59 {//中国剩余定理不互质
 60     bool flag=false;
 61     int64 n1=a[0], b1=b[0],x,y;
 62     for (int i=1;i<len;i++)
 63     {
 64         int64 n2=a[i], b2=b[i];
 65         int64 bb=b2-b1;
 66         int64 d=Extend_Euclid (n1,n2,x,y);
 67         if (bb % d)        //模线性解k1时发现无解
 68         {
 69             flag = true;
 70             break;
 71         }
 72         int64 k = bb/d*x;  //相当于求上面所说的k1【模线性方程】
 73         int64 t = n2/d;
 74         if (t < 0) t = -t;
 75         k = (k % t + t) % t;    //相当于求上面的K`
 76         b1 = b1 + n1*k;
 77         n1 = n1 / d * n2;
 78     }
 79     if (flag) return -1;  //无解
 80     return b1;
 81 }
 82 //求模线性方程组x=ai(mod ni),ni可以不互质
 83 int64 China_Reminder2(int len, int64* a, int64* n)
 84 {
 85     int64 a1=a[0],n1=n[0];
 86     int64 a2,n2;
 87     for(int i = 1; i < len; i++)
 88     {
 89         int64 aa,nn;
 90         a2 = a[i],n2=n[i];
 91         if(!merge(a1,n1,a2,n2,aa,nn))
 92             return -1;
 93         a1 = aa;
 94         n1 = nn;
 95     }
 96     Mod = n1;
 97     return (a1%n1+n1)%n1;
 98 }
 99 
100 int num;
101 
102 void datecin()
103 {
104     for(int i=0;i<num;i++)
105     {
106         scanf("%I64d",&a[i]);
107     }
108     for(int i=0;i<num;i++)
109     {
110         scanf("%I64d",&b[i]);
111     }
112 }
113 
114 int main()
115 {
116     int t;
117     int counts=0;
118     scanf("%d",&t);
119     while(t--)
120     {
121         scanf("%d",&num);
122         datecin();
123         if (num==1 && b[0]==0)  //特判只一次且没有剩余的情况
124         {
125             printf("Case %d: %I64d
",++counts,a[0]);
126             continue;
127         }
128         printf("Case %d: %I64d
",++counts,Chinese_Remainder(b,a,num));
129         //printf("Case %d: %I64d
",++counts,China_Reminder2(num,b,a));
130     }
131 
132     return 0;
133 }

两个中国剩余定理均可使用,只是第一种只需要ex_gcd函数,比较方便,而第二种需要几乎所有函数

原文地址:https://www.cnblogs.com/byzsxloli/p/5465796.html