C. Pull Your Luck
While James is gone on business, Vesper takes her time and explores what the legendary Casino Royale has to offer to people who are fond of competitive programming.
Her attention was grabbed by the very new "Pull Your Luck" roulette which functions in a pretty peculiar way. The roulette's wheel consists of $n$ sectors number from $0$ to $n - 1$. There is no ball and the winning sector is determined by a static arrow pointing to one of the sectors. Sectors' indexes go in the natural order and the wheel always spins in the direction of indexes increment. That means that sector $i + 1$ goes right after sector $i$ for all $i$ from $0$ to $n - 2$, and sector $0$ goes right after sector $n - 1$.
After a bet is made, the player is allowed to pull the triggering handle herself and cause the wheel to spin. If the player's initial pull is made with the force equal to positive integer $f$, the wheel will spin for $f$ seconds. During the first second it will advance $f$ sectors, the next second it will advance $f - 1$ sectors, then $f - 2$ sectors, and so on until it comes to a complete stop. After the wheel comes to a complete stop, the sector which the arrow is pointing to is the winning one.
The roulette's arrow currently points at sector $x$. Vesper knows that she can pull the handle with any integer force from $1$ to $p$ inclusive. Note that it is not allowed to pull the handle with force $0$, i. e. not pull it all. The biggest prize is awarded if the winning sector is $0$. Now Vesper wonders if she can make sector $0$ win by pulling the triggering handle exactly once?
Input
The first line of the input contains a single integer $t$ ($1 \leq t \leq 10^4$) — the number of test cases. Then follow $t$ lines containing one test description each.
Each test description consists of three integers $n$, $x$ and $p$ ($3 \leq n \leq 10^5$, $0 \leq x < n$, $1 \leq p \leq 10^9$). They are the number of sectors on the wheel, the current sector the arrow points at, and the maximum force that Vesper can pull the handle with, respectively.
It is guaranteed that the sum of $n$ over all test cases doesn't exceed $2 \cdot 10^5$.
Output
Print $t$ lines, the $i$-th line should contain the answer for the $i$-th test case. If it is possible to pull the handle with the integer force from $1$ to $p$ in order to make sector $0$ win, print "Yes". Otherwise, print "No".
You can output the answer in any case (upper or lower). For example, the strings "yEs", "yes", "Yes", and "YES" will be recognized as positive responses.
Example
input
7 5 2 1 5 2 2 10 0 100 11 7 100 3 1 1000 31 0 10 100 49 7
output
No Yes Yes Yes No No No
Note
In the first example, the only possible way to pull the handle is with force $1$. That is not enough to make the arrow point at sector $0$, at least force $2$ is required to do so.
In the second example, Vesper can pull the handle with the force $2$ so the wheel will spin $2 + 1 = 3$ sectors ahead and the arrow will point at sector $0$.
In the third example, Vesper can pull the handle with the force $4$ so the wheel will spin $4 + 3 + 2 + 1 = 10$ sectors and will point at sector $0$ again.
In the fourth example, Vesper can pull the handle with the force $5$ so the wheel will spin $5 + 4 + 3 + 2 + 1 = 15$ sectors. That will make the wheel make one full turn plus $4$ more sectors.
In the fifth example, whatever force Vesper chooses to pull the handle with, she can only make sectors $1$ and $2$ win.
解题思路
题目看半天,又长又臭.jpg。
说白了就是问是否存在一个$i \in [1, p]$,使得$x + \sum\limits_{j=1}^{i}{j} \equiv 0 \pmod{n}$,也即$x + \dfrac{i(i+1)}{2} \equiv 0 \pmod{n}$。
首先我们知道如果$a \equiv b \pmod{n}$,那么就会有$a \cdot c \equiv b \cdot c \pmod{n}$。因此比赛的时候就想着两边同时乘上$2$,然后会得到$i(i+1) \equiv -2x \pmod{n}$,比赛的时候一直想着用扩欧来求,肯定求不出来,因为变量是二次的。
然后赛后看了眼题解想到,对哦,直接枚举$i$来看看哪个数满足这个同余方程不就行了吗。对于同余方程$i(i+1) \equiv -2x \pmod{n}$,当$i \geq n$时得到是之前重复的结果,这是因为$$i(i+1) \equiv (i \bmod n)\left((i \bmod n)+1\right) \equiv -2x \pmod{n}$$
因此$i$从$1$枚举到$\min \{ {p, n} \}$就可以判断是否存在满足上述同余方程的解。但实际上这种做法是错误的。
这是因为$x + \dfrac{i(i+1)}{2} \equiv 0 \pmod{n}$可以推出$i(i+1) \equiv -2x \pmod{n}$。但$i(i+1) \equiv -2x \pmod{n}$不一定可以推出$x + \dfrac{i(i+1)}{2} \equiv 0 \pmod{n}$,举个简单的反例还可以推出$x + \dfrac{i(i+1)}{2} \equiv \dfrac{n}{2} \pmod{n}$,而
$$
\begin{align*}
2\left(x + \dfrac{i(i+1)}{2}\right) &\equiv 2 \cdot \frac{n}{2} &\pmod{n} \\\\
2x + i(i+1) &\equiv n \equiv 0 &\pmod{n}
\end{align*}
$$
那么加个判断条件加个$x + \dfrac{i(i+1)}{2} \bmod n \ne \dfrac{n}{2}$不就可以了吗。还是不行,这就涉及到余数循环周期这个问题了。
我们先考虑原来的式子,即$x + \dfrac{i(i+1)}{2} \equiv 0 \pmod{n}$,如果代入$i = i+2n$,那么就会有$$\begin{align*} x + \dfrac{(i+2n)(i+1+2n)}{2} & = x + \dfrac{i(i+1) + 2i \cdot n + 2(i+1) \cdot n + 4n^2}{2} \\ & = x + \dfrac{i(i+1)}{2} + i \cdot n + (i+1) \cdot n + 2n^2 \\ &\equiv x + \dfrac{i(i+1)}{2} \pmod{n} \end{align*}$$
这说明对于任意的$i$,当$i \geq 2n$那么得到的结果会是之前已有的情况,或者说得到的余数是一个循环,即存在一个周期$T=2n$。如果定义$f(i) = x + \dfrac{i(i+1)}{2} \pmod{n}$,那么就会有$f(i) = f(i+T)$。
所以这就解释了为什么仅加个判断条件还是不行,因为$i$至少要枚举到$2n$。注意,我们应该关注的是原来的同余方程。
所以$i$应该从$1$枚举到$\min\{ p, 2n \}$,然后判断是否满足同余方程即可。
AC代码如下,时间复杂度为$O(n)$:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 void solve() { 5 int n, x, p; 6 scanf("%d %d %d", &n, &x, &p); 7 p = min(p, 2 * n); 8 for (int i = 1; i <= p; i++) { 9 if ((x + i * (i + 1ll) / 2) % n == 0) { 10 printf("YES\n"); 11 return; 12 } 13 } 14 printf("NO\n"); 15 } 16 17 int main() { 18 int t; 19 scanf("%d", &t); 20 while (t--) { 21 solve(); 22 } 23 24 return 0; 25 }
一个值得注意的问题是,这个周期$T=2n$是怎么得到的?其实我觉得首先你要意识到具有周期性这个性质,然后就是代入$n$,$2n$等等去试,看能不能得到$f(i) = f(i+T)$。昨天寻找周期性这个问题困扰了我一天,然后还写了这篇博文:关于多项式方程所在剩余系的余数循环周期的猜想与推导。算是学到了很多东西吧。
参考资料
Nebius Welcome Round Editorial:https://codeforces.com/blog/entry/113830
Nebius Welcome Round (Div. 1 + Div. 2) C:https://zhuanlan.zhihu.com/p/613470409
标签:sector,Pull,handle,pull,pmod,dfrac,Luck,Your,equiv From: https://www.cnblogs.com/onlyblues/p/17216164.html