C. Vika and Price Tags
题意:
初始两串数列\(a, b\),对于第\(i\)个数,令\(c_i=|a_i-b_i|\),然后将数列\(a=b,b = c\)。重复这样的操作,问是否可能让\(a\)串全部变成0。
思路:
这题实际上之前已经发过,但最近打牛客对这题有了新的理解,所以来记录一下。
让我们假设\(a >> b\),那么我们模拟的过程就会变成如下这样:
\[(a, b)\rightarrow (b,a-b)\rightarrow (a-b,a-2b)\rightarrow (a-2b,b)\rightarrow (b,a-3b)\rightarrow (a-3b,a-4b)\rightarrow \\(a-4b,b)\rightarrow (b,a-5b)\rightarrow (a-5b,a-6b)\rightarrow (a-6b,b) \rightarrow (b,a-7b) \] 仔细观察可以发现,\((a-kb,b)\)和\((b,a-tb)\)的结构在反复出现,且\(k\)一定为偶数,\(t\)一定为奇数。
对于这种一个数不断地减去另一个数的形式,我们可以回想起,裴蜀定理得,\(a,b\)辗转相减只可能得到其$gcd $的若干倍(gcd辗转相除的原理)
也即是说,对于\((a,b)\)我们可以将其变成\((a\%b,b)/(b,a\%b)\),记\(t = a/ b\)
对于\(t\)为奇数,\((a,b)\rightarrow(b,a \% b)\),次数为\((t - 1)/2 * 3 + 1\)
对于\(t\)为偶数,\((a, b) \rightarrow (a\%b,b)\),次数为\(t/2*3\)
int cal(int a, int b){
if(a == 0){
return 0;
}
else if(b == 0){
return 1;
}
if(a >= b){
int t = a / b;
if(t % 2){
return cal(b, a % b) + 1 + (t - 1) / 2 * 3;
}
else{
return cal(a % b, b) + t / 2 * 3;
}
}
else{
return 1 + cal(b, abs(a - b));
}
}
void QAQ(){
int n;
cin >> n;
vector<int> a(n + 1), b(n + 1);
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> b[i];
set<int> s;
for(int i = 1; i <= n; i ++){
if(a[i] == 0 && b[i] == 0) continue;
s.insert(cal(a[i], b[i]) % 3);
}
if(s.size() <= 1) cout << "YES" << endl;
else cout << "NO" << endl;
}
标签:return,885,Tags,int,Price,Vika,rightarrow From: https://www.cnblogs.com/woods4325/p/17608568.html裴蜀定理得,\(a,b\)辗转相减只可能得到其$gcd $的若干倍(gcd辗转相除的原理)