特判 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
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个字符颜色匹配的方案数即可。
一开始 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
设第 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即可
考虑先手第一次从序列中间选择了一个格子,将序列分成了左右两部分,则接下来的操作必然是从当前位置出发向左/右交替选完,只剩下另一部分。
设奇数格子的 ∑ a i = A \sum a_i=A ∑ai=A,偶数格子的 ∑ a i = B \sum a_i=B ∑ai=B