前言
今天早上模拟赛刚考这题,考场虽然写出来(思路和其他题解好像不太一样),但是不太会证明,若题解有不当之处或者代码可以被举出反例,请及时联系 @guozhetao 改正。
思路
本题解定义 b h ( i , j ) bh(i,j) bh(i,j) 为将第 i i i 个点与第 j j j 个点依据题意变换(如果颜色相同,则为它们的相同颜色;如果颜色不同,则为一个颜色与它们都不同的颜色)。
因为 2 ≤ n ≤ 400000 2 \le n \le 400000 2≤n≤400000,因此直接模拟肯定过不了。
观察样例:
W
BR
RWB
RRBB
可以发现最上方的 W
根据题意是由 B
与 R
组合而成,而最低下一行的左右两边分别是 B
与 R
。
考场上,我尝试其他几种情况,发现当最后一行个数是 4 4 4 时,顶端的字母只和底端左右两个端点有关(且刚好与题目所提供的变化方式相同),于是我猜想:当最后一行个数为 3 k + 1 3^k + 1 3k+1 时,顶端只和底端左右端点有关。
于是,我们每次对于 n n n,找到最大的 k k k 使得 3 k + 1 ≤ n 3^k + 1 \leq n 3k+1≤n,并枚举第 n − 3 k n - 3 ^ k n−3k 层的情况:当 ( i + 3 k ≤ n ) (i + 3 ^ k \leq n) (i+3k≤n) 时依次更新 b i = b h ( i , i + 3 k ) b_i = bh(i,i + 3^k) bi=bh(i,i+3k),则此时我们将一个长度为 n n n 的序列变为一个长度为 n − 3 k n - 3^k n−3k 的序列,然后将 n ← n − 3 k n \gets n - 3^k n←n−3k。重复以上操作直至 n < 4 n < 4 n<4。
操作后若 n ≠ 1 n \not= 1 n=1,因为 n n n 很小,将最后的几行依照题意枚举即可。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n;
char b[400005];
int find(int x) {
int tot = 1;
while(x >= 3) {
x /= 3;
tot *= 3;
}
return tot;
}
signed main() {
//freopen("B.in","r",stdin);
//freopen("B.out","w",stdout);
scanf("%lld",&n);
for(int i = 1;i <= n;i++) cin >> b[i];
int ans = n;
while(ans >= 4) {
int x = find(ans - 1);//寻找最大的 3^k
//依题意进行模拟
for(int i = 1;i + x <= n;i++) {
if(b[i] == b[i + x]) continue;
else if(b[i] == 'B' and b[i + x] == 'W') b[i] = 'R';
else if(b[i] == 'W' and b[i + x] == 'B') b[i] = 'R';
else if(b[i] == 'W' and b[i + x] == 'R') b[i] = 'B';
else if(b[i] == 'R' and b[i + x] == 'W') b[i] = 'B';
else b[i] = 'W';
}
ans -= x;
//printf("%lld\n",ans);
}
//最后几行自己模拟
for(;ans > 1;ans--) {
for(int i = 1;i < ans;i++) {
if(b[i] == b[i + 1]) continue;
else if(b[i] == 'B' and b[i + 1] == 'W') b[i] = 'R';
else if(b[i] == 'W' and b[i + 1] == 'B') b[i] = 'R';
else if(b[i] == 'W' and b[i + 1] == 'R') b[i] = 'B';
else if(b[i] == 'R' and b[i + 1] == 'W') b[i] = 'B';
else b[i] = 'W';
}
}
cout<<b[1]<<endl;
return 0;
}
证明过程
因个人能力原因,本部分有参照这篇题解,若无法理解可跳过本部分。
设最底层个数为
m
(
m
=
3
k
+
1
)
m(m = 3 ^ k + 1)
m(m=3k+1),若令 B
为
0
0
0,W
为
1
1
1,R
为
2
2
2,则顶层
p
≡
−
∑
b
i
×
(
m
−
1
)
!
i
!
×
(
m
−
1
−
i
)
!
(
m
o
d
3
)
p \equiv -\sum b_i \times \dfrac{(m - 1)!}{i! \times (m - 1 - i)!} \pmod 3
p≡−∑bi×i!×(m−1−i)!(m−1)!(mod3)。
由于 m − 1 ≡ 0 ( m o d 3 ) m -1 \equiv 0 \pmod 3 m−1≡0(mod3),则当 0 < i < m 0 < i < m 0<i<m 时, ( m − 1 ) ! i ! × ( m − 1 − i ) ! ≡ 0 ( m o d 3 ) \dfrac{(m - 1)!}{i! \times (m - 1 - i)!} \equiv 0 \pmod 3 i!×(m−1−i)!(m−1)!≡0(mod3);
因此: p ≡ − ∑ b i × ( m − 1 ) ! i ! × ( m − 1 − i ) ! ≡ 6 − b 0 − b m ( m o d 3 ) p \equiv -\sum b_i \times \dfrac{(m - 1)!}{i! \times (m - 1 - i)!} \equiv 6-b_0 - b_m\pmod 3 p≡−∑bi×i!×(m−1−i)!(m−1)!≡6−b0−bm(mod3)。
所以当最后一行个数为 3 k + 1 3^k + 1 3k+1 时,顶端只和底端左右端点有关。