题目:https://codeforces.com/contest/1162
题解:https://codeforces.com/blog/entry/66878
代码:https://github.com/dezhonger/Algorithm/tree/master/codeforces/round557%20div2
A. Zoning Restrictions Again
题意:给了每个一些区间的最大值,求最大和
暴力
B. Double Matrix
给两个矩阵,问是否可以交换同样位置的数,让两个矩阵在每行每列为递增的
贪心,先保证的第一个矩阵可以(尽量选小的数),再去判断第二个矩阵
C. Hide and Seek
给了一些询问,使所有回答均为no,我们可以在其中一个询问之前或之后,换掉物品所在的格子(只能换一次),求有多少种方法来换这个物品
1、假设出现了数x,那么(x, x)不行
2、其次,如果两个数x,y在询问里出现过,并且y在x后面,那么(x,y)不行
可以这样做,保存每个数第一次出现的位置和最后一次出现的位置,即可快速判断条件2
D. Chladni Figure
求图形是否是旋转对称的
枚举N的约数,对每个线段做旋转,判断旋转后和旋转前的线段集合是否相同。
#include <cstdio>
#include <unordered_set>
#include <vector>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define reps(i, a, b) for(int i = (a); i < (b); i++)
#define pb push_back
typedef long long ll;
int n, m;
ll chord(ll x, ll y) {
//merge to a number
x %= n;
y %= n;
if (x > y) swap(x, y);
return (x << 32) | y;
}
ll rorate(ll c, int a) {
ll x = c >> 32;
ll y = c & ((1LL << 32) - 1);
return chord(x + a, y + a);
}
int main() {
unordered_set<ll> us;
vector<ll> cs;
scanf ("%d%d", &n, &m);
reps (i, 0, m) {
int x, y;
scanf ("%d%d", &x, &y);
ll c = chord (x, y);
cs.pb (c);
us.insert (c);
}
//divisor
reps (i, 1, n) {
if (n % i) continue;
bool ok = true;
for (auto &x : cs) {
if (!us.count (rorate (x, i))) {
ok = false;
break;
}
}
if (ok) {
printf ("Yes\n");
return 0;
}
}
printf ("No\n");
return 0;
}
E. Thanos Nim
很多堆每次两个人轮流玩,每次可以选择n/2堆石子,拿走一些,每堆拿走的石子个数可以不同。谁不能操作为数。求先手的输赢。
博弈,先说结论:判断假设最小堆的数为x,看堆为x的个数是否小于等于n/2.
翻译下题解:
谁被迫要减少最小堆的数量,那么这个人lose
<=n/2,为必胜点,>n/2为必败点,如果在胜点,那么有决策选使下一个点为必败点;如果在必败点,无论怎么决策,下一个点均为必胜点
分界点就在于最小堆的数量是否<=n/2,
假设<=n/2,那么可以选选那些不是最小堆的堆,把他们减少到最小的即可(win->lose)
如果>n/2,那么无论怎么选,肯定会选到至少一个最小堆,最多选到n/2个最小堆,那么结果必然是最小堆的数量在[1,n/2]之间(lose->win)
F. Palindrome XOR
一个包含‘0’ '1' ‘?’的字符串,第一个字符为'1',求满足下列(a, b)的数量
1 <= a < b < 2^m
a,b的二进制都是回文的(不包含前导0)
a xor b和字符串是匹配的(?可以为0或1)