标签:call ace ref tree node nsa 同余 就是 nod
\(excrt\) \(\text{是用来解决当模数不互质的情况下的普通}crt\text{情况的}\)
具体见P4777
事实上和\(crt\)没有什么关系
主要思想是:我们不断的合并两个同余方程,最后合并到只剩一个。
对于方程组
\(\begin{cases} x \equiv b_1\ ({\rm mod}\ a_1) \\ x\equiv b_2\ ({\rm mod}\ a_2) \\ \end{cases}\)
我们考虑合并 这两个同余方程组
我们化为
\(\begin{cases} x =a_1k_1+b_1\\ x=a_2k_2+b_2 \\ \end{cases}\)
\(\therefore a_1k_1+b_1=a_2k_2+b_2\)
\(\therefore a_1k_1-a_2k_2=b_2-b_1\)
这个可以用\(exgcd\)求出一组当\(a_1k_1-a_2k_2=(a1,a2)\)时的特解
我们将\(x*gcd(a1,a2)/(b_2-b_1)\)就可以得到原方程的一组解
那么我们可以回代解出\(a_1,b_1,a_2,b_2\)
然后
我们将\(b_2-b_1\)作为新的\(x\),\([a_1,a_2]\)作为新的模数,\(a_1k_1-a_2k_2\)作为新的余数
我们就成功的合并了两个方程
然后不停的合并下去,最后的\(x\)就是答案了
代码
/*
@Date : 2018-10-07 11:01:36
@Author : Adscn (1349957827@qq.com)
@Link : https://www.cnblogs.com/LLCSBlog
*/
#ifdef FASTER
#pragma GCC diagnostic error "-std=c++11"
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#endif
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
typedef long long ll;
IL ll getint()
{
RG ll xi=0;
RG char ch=gc;
bool f=0;
while(ch<'0'|ch>'9')ch=='-'?f=1:f,ch=gc;
while(ch>='0'&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
return f?-xi:xi;
}
inline ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1,y=0;
return a;
}
ll gcd=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return gcd;
}
struct node{
ll mod,a;
}last,now;
istream& operator >> (istream&is,node &p)
{
cin>>p.mod>>p.a;
return is;
}
node join(node p,node q)
{
ll x,y;
ll gcd=exgcd(p.mod,q.mod,x,y);
x=(x*(__int128)(q.a-p.a)/gcd)%(q.mod/gcd);
if((q.a-p.a)%gcd)exit(1);
p.a=x*p.mod+p.a;
p.mod=p.mod/gcd*q.mod;
p.a=(p.a%p.mod+p.mod)%p.mod;
return p;
}
int main(void)
{
#ifdef ONLINE_JUDGE
// File("");
#endif
ll n;
cin>>n>>last;
for(int i=2;i<=n;i++)
{
cin>>now;
last=join(last,now);
}
cout<<last.a;
return 0;
}
标签:call ace ref tree node nsa 同余 就是 nod
原文地址:https://www.cnblogs.com/LLCSBlog/p/10202361.html