题解PKUCPC2023 C Empty up a Bottle

发布时间 2023-05-29 19:31:00作者: xiaolilsq

题解PKUCPC2023 C Empty up a Bottle

感觉这道题目好厉害啊。

题意就是有三个瓶子 ABC,每个瓶子里面都初始装有 \(M_A,M_B,M_C\) 单位体积的水,每次你可以选择将一个瓶子中倒水到另外一个瓶子,你必须保证另外一个瓶子装水量恰好翻倍,请使用若干次操作使得一个瓶子变成空的,容易发现每次操作只能是水多的倒到水少的瓶子,所以共有三种类型的操作(选择 AB 或 BC 或 AC),如果两次操作类型相同可以合并成一次操作,要求使用不超过 \(200\) 次操作。其中 \(1\le M_A,M_B,M_C\le 3\times 10^{13}\)

先只考虑两个瓶子之间相互倒,如果倒之前水量分别为 \(a,b(a>b)\),那么倒完后就是 \(a-b,2b\),或者说是 \((2a\bmod (a+b),2b\bmod (a+b))\),而 \(a+b\) 经过任意次操作后都是不变的,所以如果互相倒 \(k\) 次结果就是 \((2^ka\bmod (a+b),2^kb\bmod (a+b))\)。如果 \(a+b\) 是奇数,那么根据费马小定理,有 \(2^{\varphi(a+b)}\equiv 1\pmod{(a+b)}\),于是我们进行 \(\varphi(a+b)-1\) 次操作后可以得到 \((a/2^k\bmod (a+b),b/2^k\bmod (a+b))\),这样我们相当于可以把一个偶数除以 \(2^k\),然后剩下的值丢给另一个奇数。

既然可以实现除以 \(2^k\) 的操作,那么我们便可以借用奇数来实现辗转相减了,因为 \((a,b)\) 若干次操作后变成 \((a-(2^k-1)b,2^kb)\),我们将 \(b\) 除以 \(2^k\) 丢给另一个奇数 \(c\) 就可以得到 \((a-(2^k-1)b,b)\),而如果 \(b\) 是偶数那么操作后仍然保持 \(c\) 为奇数的性质,所以如果三个数为一个奇数两个偶数就可以直接这样辗转相减直到 \(0\) 做了。

如果三个数都是偶数可以都视作都除以 \(2\) 不影响后续求解,如果三个数两个奇数一个偶数那么两个奇数一次操作变成三个偶数再除以 \(2\) 即可。

容易发现操作次数也是满足的。