Codeforces Round 893 (Div. 2) 赛后总结
小菜鸡的赛后总结

- B好烦,最近想刷一些低分段的games类型的题,以后好快速切掉
- 题意:有两人进行游戏。先手有 a个按钮,后手有 b个按钮。还有 c个公用的按钮。每一回合,每人必须选择一个自己的按钮或者公共按钮按下,且不能选择已经按过的按钮。无法按下按钮的人输掉游戏。给出a,b,c,求出最后的获胜者
- 思路:两人优先争公共按钮,而对于先手来说,如果c不是偶数,那么a会用的更多一些,如果是偶数,则两人会平分公共按钮,这时候只要比对a和b的大小就行了,c是奇数的话先手就加1即可
void BlueFire()
{
ll a, b, c;
cin >> a >> b >> c;
a = a + c + !(c%2 == 0);
b = b + c;
if (a > b)
cout << "First" << endl;
else
cout << "Second" << endl;
return;
}
B. The Walkway
- 题意:数轴上的一些点上有一些饼干摊。现从 x=1走到 x=n,在每个点,如果下面条件至少有一个满足,则会吃一枚饼干:
- x=1
- 当前位置 - 上次吃饼干的位置 至少为 d
- 当前位置有饼干摊。
现在恰好撤去任意一个饼干摊,要求使从 x=1到 x=n 路程上吃的饼干总数最少。问最少要吃多少饼干?有多少种达成最少的方案?
- 思路:先计算出不撤也就是原本的情况下应该吃多少饼干,然后枚举撤去某个饼干摊,减去它造成的影响(即和前面最近的饼干摊距离除以d,以及后面最近的饼干摊距离除以d),再加上撤去它又应该吃多少饼干。比对答案即可
void BlueFire()
{
int n, m, k;
cin >> n >> m >> k;
vector<int> v(m + 2);
for (int i = 1; i <= m; i++)
cin >> v[i];
v[0] = 1, v[m + 1] = n + 1;
ll res = 1; // 起点
for (int i = 1; i <= m + 1; i++)
{
res += (v[i] - v[i - 1] - 1) / k;
if (v[i] != 1 && v[i] != n + 1)
res++;
}
// 枚举删除每一个位置
ll ans = 1e9 + 1;
ll fas = 0;
for (int i = 1; i <= m; i++)
{
ll t = res;
t -= (v[i] - v[i - 1] - 1) / k + (v[i + 1] - v[i] - 1) / k; // 减去有这个摊位存在时的情况
if (v[i] != 1 && v[i] != n + 1)
t--; // 减去这个摊位
t += (v[i + 1] - v[i - 1] - 1) / k; // 新的需求
if (t < ans)
{
ans = t;
fas = 1;
}
else if (t == ans)
fas++;
}
cout << ans << " " << fas << endl;
return;
}
C. Yet Another Permutation Problem
- 题意:给出一个数字 n ,定义 d 数组为 d[i] = gcd( a[i] , a[i]%n+1 ),构造一个长度为 n 的排列 a ,使得 d 数组中不同数字的个数最大
- 思路:贪心一直枚举前一个数的两倍即可(为了使最大公因数尽可能不同)
void BlueFire()
{
int n;
cin >> n;
vector<int> h(n + 1);
for (int i = 1; i <= n; i++)
h[i] = 0;
cout << 1 << " ";
h[1] = 1;
for (int i = 1; i <= n; i++)
{
if (!h[i])
{
cout << i << " ";
h[i] = 1;
ll f = i * 2;
while (f <= n && !h[f])
{
cout << f << " ";
h[f] = 1;
f *= 2;
}
}
}
cout << endl;
return;
}