RT.
这是我的代码:( AC 100pts)
#define int __int_128
int exgcd(int a, int b, int &x, int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int res=exgcd(b,a%b,y,x);
y-=a/b*x;
return res;
}
......
struct Node{int a,mod;}; // 存储方程
il Node merge(Node a, Node b) // 请注意这个函数!
{
int x,y;
int tmp=exgcd(a.mod,-b.mod,x,y);
if((b.a-a.a)%tmp) throw "OMG, No solution!";
int p3=(b.a-a.a)/tmp;
x*=p3,y*=p3;
int new_mod=lcm(a.mod,b.mod);
assert(a.mod*x-b.mod*y==b.a-a.a);
return (Node){(((x*a.mod+a.a)%new_mod)+new_mod)%new_mod,new_mod};
}
il ll exCRT(vector<Node> dat)
{
Node tmp=*dat.begin();
for(vector<Node> :: iterator it=dat.begin()+1; it!=dat.end(); ++it)
{
// cerr<<(ll)tmp.a<<endl;
tmp=merge(tmp,*it);
}
return (ll)tmp.a;
}
......
但是如果我们将 merge 函数换成如下写法,会发现连样例都过不去:
il Node merge(Node a, Node b)
{
ll __x,__y;
int tmp=exgcd(a.mod,b.mod,__x,__y);
if((b.a-a.a)%tmp) throw "OMG, No solution!";
int p1=a.mod/tmp,p2=-b.mod/tmp,p3=(b.a-a.a)/tmp;
exgcd(p1,p2,__x,__y); // 注意这里
int x=__x,y=__y;
x*=p3,y*=p3;
int new_mod=lcm(a.mod,b.mod);
assert(a.mod*x-b.mod*y==b.a-a.a); // 这里会 assertion failed !
return (Node){(((x*a.mod+a.a)%new_mod)+new_mod)%new_mod,new_mod};
}
但是为什么会造成这种错误呢?
这是我的推导:
\end{cases}$$ $$\implies \begin{cases}x=a_1·k_1+b_1 \\ x=a_2·k_2+b_2\end{cases} $$ $$\implies a_1·k_1-a_2·k_2 = b_2-b_1\ (\Iota)$$ 令 $$p_1=\dfrac{a_1}{\gcd(a_1,a_2)},p_2=\dfrac{a_2}{\gcd(a_1,a_2)},p_3=\dfrac{b_2-b_1}{\gcd(a_1,a_2)}$$ 我们知道这道题**保证有解** 那么 $\Iota$ 式可以化为 $p_1k1-p2k2=p3$ 那么不应该可以 `exgcd(p1,p2,x,y)` 求出一组解,然后把 `x*=p3,y*=p3` 吗? 可是这样 WA 了 qwq 求 dalao 解答!