C. Vika and Price Tags
Vika came to her favorite cosmetics store "Golden Pear". She noticed that the prices of $n$ items have changed since her last visit.
She decided to analyze how much the prices have changed and calculated the difference between the old and new prices for each of the $n$ items.
Vika enjoyed calculating the price differences and decided to continue this process.
Let the old prices be represented as an array of non-negative integers $a$, and the new prices as an array of non-negative integers $b$. Both arrays have the same length $n$.
In one operation, Vika constructs a new array $c$ according to the following principle: $c_i = |a_i - b_i|$. Then, array $c$ renamed into array $b$, and array $b$ renamed into array $a$ at the same time, after which Vika repeats the operation with them.
For example, if $a = [1, 2, 3, 4, 5, 6, 7]$; $b = [7, 6, 5, 4, 3, 2, 1]$, then $c = [6, 4, 2, 0, 2, 4, 6]$. Then, $a = [7, 6, 5, 4, 3, 2, 1]$; $b = [6, 4, 2, 0, 2, 4, 6]$.
Vika decided to call a pair of arrays $a$, $b$ dull if after some number of such operations all elements of array $a$ become zeros.
Output "YES" if the original pair of arrays is dull, and "NO" otherwise.
Input
Each test consists of multiple test cases. The first line contains a single integer $t$ ($1 \le t \le 10^4$) — the number of test cases. The description of the test cases follows.
The first line of each test case contains a single integer $n$ ($1 \le n \le 10^5$) — the number of items whose prices have changed.
The second line contains $n$ integers $a_1, a_2, \ldots, a_n$ ($0 \le a_i \le 10^9$) — the old prices of the items.
The third line contains $n$ integers $b_1, b_2, \ldots, b_n$ ($0 \le b_i \le 10^9$) — the new prices of the items.
It is guaranteed that the sum of $n$ over all test cases does not exceed $10^5$.
Output
For each test case, output "YES" if the pair of price arrays is dull, and "NO" otherwise.
You can output each letter in any case (lowercase or uppercase). For example, the strings "yEs", "yes", "Yes", and "YES" will be accepted as a positive answer.
Example
input
9 4 0 0 0 0 1 2 3 4 3 1 2 3 1 2 3 2 1 2 2 1 6 100 23 53 11 56 32 1245 31 12 6 6 6 7 1 2 3 4 5 6 7 7 6 5 4 3 2 1 3 4 0 2 4 0 2 3 2 5 2 1 3 4 2 6 1 4 2 2 0 0 0 3
output
YES YES NO NO YES YES NO YES YES
Note
In the first test case, the array $a$ is initially zero.
In the second test case, after the first operation $a = [1, 2, 3], b = [0, 0, 0]$. After the second operation $a = [0, 0, 0], b = [1, 2, 3]$.
In the third test case, it can be shown that the array $a$ will never become zero.
解题思路
首先可以发现数组中对每一位的操作都是相互独立的,因此可以先求出每个$a_i$第一次变成$0$时共操作了几次,假设为$c_i$次,然后模拟一下可以发现再操作$3$次后$a_i$又变成了$0$,因此看一下每个$c_i \bmod 3$是否都相同,如果都一样说明某一时刻可以将数组$a$变成全$0$,否则无解(如果初始时$a_i = b_i = 0$那么可以忽略,因此始终都是$0$)。
大致思路就是上面说的那样,不过首先需要证明反复执行这个操作可以得到$0$。对于$a_i$和$b_i$至少有一个不为$0$的情况,如果有$a_i \geq b_i$,那么对$(a_i, b_i)$执行一次操作后就会变成$(b_i, a_i - b_i)$,数对总和从$a_i + b_i$减小到$a_i$。如果$a_i < b_i$,在两次操作后就会变成$(b_i - a_i, a_i)$,数对总和从$a_i + b_i$减少到$b_i$。由于$a_i$和$b_i$始终是非负整数,因此其总和不可能一直减少,因此$a_i$和$b_i$一定会有一个变成$0$。
当经过$c_i$次操作后,$(a_i, b_i)$变成$(0, d)$(实际上$d = \operatorname{gcd}(a_i, b_i)$),再经过$3$次操作有$(0, d) \to (d, d) \to (d, 0) \to (0, d)$,即最终会形成一个周期为$3$的循环。因此要判断是否能将数组$a$变成全$0$,就要看每一个$c_i$模$3$是否都相同。因此求出$c_i$就是关键。
假设$a_i \geq b_i$(否则执行一次操作即可),令$a_i = k \cdot b_i + r$,那么有
\begin{array}{c}
\left( k \cdot b_i + r, \, b_i \right) \\ \downarrow \\
\left( b_i, \, (k-1) \cdot b_i + r \right) \\ \downarrow \\
\left( (k-1) \cdot b_i + r, \, (k-2) \cdot b_i + r \right) \\ \downarrow \\
\left( (k-2) \cdot b_i + r, \, b_i \right) \\ \downarrow \\
\left( b_i, \, (k-3) \cdot b_i + r \right) \\ \downarrow \\
\left( (k-3) \cdot b_i + r, \, (k-4) \cdot b_i + r \right) \\ \downarrow \\
\left( (k-4) \cdot b_i + r, \, b_i \right) \\ \downarrow \\
\left( b_i, \, (k-5) \cdot b_i + r \right) \\ \downarrow \\
\left( (k-5) \cdot b_i + r, \, (k-6) \cdot b_i + r \right) \\ \downarrow \\
\left( (k-6) \cdot b_i + r, \, b_i \right) \\ \vdots
\end{array}
不断的操作下去最终会得到$(b_i, r)$或$(r, b_i)$。令$k$为奇数,模拟一下可以发现经过$3 \cdot \left\lfloor \frac{k}{2} \right\rfloor + 1$次操作后就会得到$(b_i, r)$。令$k$为偶数,经过$3 \cdot \frac{k}{2}$次操作后就会得到$(r, b_i)$。因此我们可以写个递归来求出$(a_i, b_i)$变成$(0, d)$所需要的次数$c_i$,由于每一次都是对小于自身的数取模,因此相应的时间复杂度为$O(\log{a_i})$。
AC代码如下,时间复杂度为$O(n \log{A})$:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5 + 10; 5 6 int a[N], b[N]; 7 8 int dfs(int a, int b) { 9 if (!a) return 0; // a=0不需要操作 10 if (!b) return 1; // b=0再操作一次即可 11 if (a < b) return 1 + dfs(b, b - a); // a>b,操作一次使得a<=b 12 int k = a / b; 13 if (k & 1) return k / 2 * 3 + 1 + dfs(b, a % b); // k是奇数,最后得到(b, r) 14 return k / 2 * 3 + dfs(a % b, b); // k是偶数,最后得到(r, b) 15 } 16 17 void solve() { 18 int n; 19 scanf("%d", &n); 20 for (int i = 0; i < n; i++) { 21 scanf("%d", a + i); 22 } 23 for (int i = 0; i < n; i++) { 24 scanf("%d", b + i); 25 } 26 set<int> st; 27 for (int i = 0; i < n; i++) { 28 if (!a[i] && !b[i]) continue; // 跳过a[i]和b[i]均为0的情况 29 st.insert(dfs(a[i], b[i]) % 3); 30 if (st.size() > 1) { // 存在至少两个不同的ci%3 31 printf("NO\n"); 32 return; 33 } 34 } 35 printf("YES\n"); 36 } 37 38 int main() { 39 int t; 40 scanf("%d", &t); 41 while (t--) { 42 solve(); 43 } 44 45 return 0; 46 }
参考资料
Codeforces Round #885 (Div.2) Editorial:https://codeforces.com/blog/entry/118333
标签:right,Tags,cdot,Price,test,array,Vika,YES,left From: https://www.cnblogs.com/onlyblues/p/17673661.html