**B.rng_10s
特判 A < B A<B A<B和 D < B D<B D<B的情况。
问题转化为初始坐标为
A
−
B
A-B
A−B,每次可以移动
−
B
-B
−B或
+
D
−
B
+D-B
+D−B,要求点始终落在
[
C
−
B
+
1
,
C
−
B
+
D
]
[C-B+1,C-B+D]
[C−B+1,C−B+D]中。
发现可达坐标在模
gcd
(
B
,
D
)
\gcd(B,D)
gcd(B,D)意义下与
A
A
A同余,那么找到最小的一个
x
≡
A
(
m
o
d
gcd
(
B
,
D
)
)
x\equiv A\pmod {\gcd(B,D)}
x≡A(modgcd(B,D))且
x
≥
C
−
B
+
1
x\geq C-B+1
x≥C−B+1的数,
x
≥
0
x\geq 0
x≥0则输出"Yes",否则输出"No"。
p.s 具体实现时,可以直接找到第一个 < 0 <0 <0的 x x x,判断其是否 ≥ C − B + 1 \geq C-B+1 ≥C−B+1
C.String Coloring
2 n , n ≤ 18 2n,n\leq 18 2n,n≤18,明示折半枚举
2 n 2^n 2n枚举前 n n n个字符的颜色,两个串的具体值都能够被确定, 然后 n 2 n^2 n2DP求出后 n n n个字符颜色匹配的方案数即可。
*D.Histogram Coloring
一开始 1 0 9 10^9 109还以为是矩阵快速幂什么的,好zz。。。
考虑相邻两行(假设列数相同),它们要么对应位置颜色都相同(两行都是颜色交错的),要么都全部不同。按高度 D P DP DP即可。
pair<int, int> solve(int l, int r, int base, vector<int> &a) {
int x = *min_element(a.begin() + l, a.begin() + r), coef = 1, all = 1, number = 0;
for (int i = l; i < r; ++i) {
if (a[i] != x) {
int j = i;
while (j + 1 < r && a[j + 1] != x) {
++j;
}
pair<int, int> value = solve(i, j + 1, x, a);
i = j;
coef = mul(coef, value.first);
all = mul(all, add(value.first, value.second));
} else {
++number;
}
}
return make_pair(mul(coef, power(2, x - base)), add(mul(all, power(2, number)), mul(coef, sub(power(2, x - base), 2))));
}
//ans=solve(0, n, 0, a).second
*E.Synchronized Subsequence
设第
i
i
i个
a
a
a的位置为
a
i
a_i
ai,第
i
i
i个
b
b
b的位置为
b
i
b_i
bi
可以把序列分成若干个极小段,满足每段内
c
n
t
a
=
c
n
t
b
cnt_a=cnt_b
cnta=cntb,且所有
a
i
<
b
i
a_i<b_i
ai<bi或所有
a
i
>
b
i
a_i>b_i
ai>bi。
若
a
i
<
b
i
a_i<b_i
ai<bi,这一段的最优解必然形如
a
b
a
b
a
b
.
.
.
ababab...
ababab...(去掉其中连续的
a
a
a)
若
a
i
>
b
i
a_i>b_i
ai>bi,这一段的最优解必然是一段后缀。
若选择了某段,必然选择了这段的最优解,所以求出每段最优解后 d p dp dp即可
*F.Manju Game
考虑先手第一次从序列中间选择了一个格子,将序列分成了左右两部分,则接下来的操作必然是从当前位置出发向左/右交替选完,只剩下另一部分。
设奇数格子的 ∑ a i = A \sum a_i=A ∑ai=A,偶数格子的 ∑ a i = B \sum a_i=B ∑ai=B
- n n n为偶数。若先手从中间选了一个格子,剩下的格子必然分成了一个奇数段和一个偶数段,后手选择偶数段往下走,到奇数段时就变成了后手可以先决策,答案不会比先手一开始选定一种奇偶性的格子走更优。所以 n n n为偶数时的先手答案为 max ( A , B ) \max(A,B) max(A,B)
-
n
n
n为奇数。若先手选择了一个偶数格子,剩下的格子必然分成了两个奇数段,后手任意去掉一边后转成了另一边的子问题;否则先手选择了一个奇数格子,能保证的最优答案为
A
A
A。
可以将每次选择的偶数格子看做关键点,最终序列会被这些关键点划分成若干段,且有且仅有一段,先手选择了其中所有奇数格子,其它段先手都选择了其中偶数格子。先手的答案就是关键点加上每段选择的值的和。
先手可以决策出段的划分:构造一个决策二叉树,每次往后手选择的另一侧走;后手可以决策出哪一段先手选择奇数格子:控制在决策二叉树上向下走的路线。
考虑二分答案 m i d mid mid,判断先手的答案是否 ≥ B + m i d \geq B+mid ≥B+mid,相当于判断是否存在一种划分方式,使得每一段中奇数格子值-偶数格子值 ≥ m i d \geq mid ≥mid。
贪心判断即可。