码迷,mamicode.com
首页 > 其他好文 > 详细

关于中国剩余定理及同余方程组求解

时间:2018-08-17 23:40:16      阅读:895      评论:0      收藏:0      [点我收藏+]

标签:template   targe   namespace   gcc   计算机   sed   ++   new   reg   

上个月去清北学堂

膜拜牛逼滴 ZHXdalao

他在讲求解同余方程组时说了他个人独创的一种牛逼算法 -----------------------大数翻倍法

说白了就是小学奥赛

例如:

我们在求解一组同余方程组

①x≡3(mod 5)

②x≡6(mod 7)

③x≡11(mod 23)

有些dalao一眼就看出来了 但是对不起 我们需要用计算机求解

至于什么扩欧求解我压根也不讲并且也不会

首先

我们假设 最终解ans=1   每次翻的数res=1

十分明显ans不满足①

那么就让ans翻滚吧  每一次加上res 翻呀翻呀翻呀翻呀翻呀

直到ans=3 可以 那就下一组

可是到了下一组 我想翻得快一些同时维护上面的同余性质 怎末办怎末办

可以考虑把res更新为TA与这个模数的LCM

于是res更新为 5

到了② ans在翻倍同时保持②以前方程的同余性质

这次ans翻成13 同时res更新为35

这时我们可以检验一下 把更新后的ans带入① 依然成立

为什么 ??????????

因为我们每次加上res 实质上是加了前面模数的共同LCM

所以同余性质不变

③同理 ans更新为678 res更新为805

带入同余方程组 依然成立

完美求解   

至于TA的性能 本蒟蒻还没进行过多试验 不过可以提供一道板子题

https://www.luogu.org/problemnew/show/P1495

据说ZHXdalao 用这个方法秒杀所有中国剩余定理的题

好了 不多说了 一言不合上代码

技术分享图片
 1 #pragma GCC optimize(3)
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<cstdlib>
 8 #include<string>
 9 #include<queue>
10 #include<map>
11 #include<stack>
12 #include<list>
13 #include<set>
14 #include<deque>
15 #include<vector>
16 #include<ctime>
17 #define ll long long
18 #define inf 0x7fffffff
19 #define N 500008
20 #define IL inline
21 #define M 1008611
22 #define D double
23 #define ull unsigned long long
24 #define R register
25 using namespace std;
26 template<typename T>void read(T &a)
27 {
28     T x=0,f=1;char ch=getchar();
29     while(!isdigit(ch))
30     {
31         if(ch==-)f=0;ch=getchar();
32     }
33     while(isdigit(ch))
34     {
35         x=(x<<1)+(x<<3)+ch-0;ch=getchar();
36     }
37     a=f?x:-x;
38 }
39 /*-------------OI使我快乐-------------*/
40 ll gcd(ll xi,ll yi){
41     if(xi<yi) swap(xi,yi);
42     ll ri=xi%yi;
43     while(ri){
44         xi=yi;yi=ri;
45         ri=xi%yi;
46     }
47     return yi;
48 }
49 ll n;
50 ll ans=1,res=1;
51 ll num1[20],num2[20];
52 int main()
53 {
54 //    freopen(".in","r",stdin);
55 //    freopen(".out","w",stdout);
56     read(n);
57     for(R ll i=1;i<=n;++i) read(num1[i]),read(num2[i]);
58     for(R ll i=1;i<=n;++i){
59         if(ans%num1[i]!=num2[i])
60          while(ans%num1[i]!=num2[i]) ans+=res;
61         res=res*num1[i]/gcd(res,num1[i]); 
62     }
63     printf("%lld\n",ans);
64 //    fclose(stdin);
65 //    fclose(stdout);
66     return 0;
67 }
View Code

若有认为存在版权抄袭问题 请及时与我联络

关于中国剩余定理及同余方程组求解

标签:template   targe   namespace   gcc   计算机   sed   ++   new   reg   

原文地址:https://www.cnblogs.com/LovToLZX/p/9495451.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!