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\n",++counts,a[0]); 126 continue; 127 } 128 printf("Case %d: %I64d\n",++counts,Chinese_Remainder(b,a,num)); 129 //printf("Case %d: %I64d\n",++counts,China_Reminder2(num,b,a)); 130 } 131 132 return 0; 133 }
两个中国剩余定理均可使用,只是第一种只需要ex_gcd函数,比较方便,而第二种需要几乎所有函数