Strange Way to Express Integers POJ 2891(中国剩余定理扩展)

原题

题目链接

题目分析

题意很明确,这里的模数是不互质的,因此不能直接套中国剩余定理.这里稍微讲一下中国剩余定理的扩展,假设前i个方程的特解为ans(i),通解为x(i)=ans(i)+k*lcm(前i个模数).把x(i)代入到第i+1个方程,用扩展欧几里得定理求解k=k0,ans(i+1)=ans(i)+k0*lcm(前i个模数),则x(i+1)=ans(i+1)+lcm(前i+1个模数).大概思路就是这样,但有些细节需要注意一下,求出来的k0,ans(i+1)需要用求模的方法缩小一下.

代码

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <utility>
 6 #include <ctime>
 7 #include <cmath>
 8 #include <cstring>
 9 #include <string>
10 #include <stack>
11 #include <queue>
12 #include <vector>
13 #include <set>
14 #include <map>
15 
16 using namespace std;
17 typedef unsigned long long ULL;
18 typedef __int64 LL;
19 typedef long double LB;
20 const int INF_INT=0x3f3f3f3f;
21 const LL INF_LL=0x3f3f3f3f3f3f3f3f;
22 
23 vector<LL> a,m;
24 
25 LL exgcd(LL a,LL b,LL &x,LL &y)
26 {
27     if(!b)
28     {
29         x=1,y=0;
30         return a;
31     }
32     LL g=exgcd(b,a%b,y,x); //简化写法
33     y-=a/b*x; //y从下一个方程回溯回来时是下一个方程的x
34     return g;
35 }
36 
37 LL solve(LL n)
38 {
39     LL ans=0,lcm=1,x,y;
40     for(int i=0;i<n;i++)
41     {
42         if(!i) ans=a[i],lcm*=m[i];
43         else
44         {
45             LL g=exgcd(lcm,m[i],x,y),c=a[i]-ans;
46             if(c%g)
47             {
48                 ans=-1;
49                 break;
50             }
51             x*=c/g;
52             LL t=m[i]/g;
53             x=(x%t+t)%t;
54             ans+=x*lcm;
55             lcm*=m[i]/g;
56             ans=((ans%lcm)+lcm)%lcm;
57         }
58     }
59     return ans;
60 }
61 
62 int main()
63 {
64 //    freopen("std.in","r",stdin);
65 //    freopen("std.out","w",stdout);
66     LL k;
67     while(~scanf("%lld",&k))
68     {
69         m.clear(),a.clear();
70         LL x,y;
71         for(int i=0;i<k;i++) scanf("%lld %lld",&x,&y),m.push_back(x),a.push_back(y);
72         printf("%lld\n",solve(k));
73     }
74     return 0;
75 }

 

posted @ 2019-08-31 09:06  VBL  阅读(130)  评论(0编辑  收藏  举报