Codeforces Educational Round 84 题解
UPD:对部分
CF1327A Sum of Odd Integers
我才不会告诉你们这道题我错了3次才AC
首先我们要明白一个事实:奇数个奇数的和是奇数,偶数个奇数的和是偶数。如果我们要把
于是我们得到:
条件1:n \equiv k \pmod 2
接下来我们考虑拆成
其实只要满足
举个栗子:
而前
条件2:n \ge k^2
综上,AC代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
//ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--)
{
int n,k;
cin >> n >> k;
if(n % 2 == k % 2 && n >= k * k)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
CF1327B Princesses and Princes
刚开始确实没有想到这道题模拟就可以了。
我们首先按照国王的规则包办婚姻,然后看看有没有剩男剩女未能配对的王子和公主,把它们配对就OK了。如果所有公主都嫁出去了,答案就是OPTIMAL。
但是这样有一个问题:题目里说了这样一句话(还特别加粗)
Note that this kingdom should not be present in the daughter's list.
后来我想了想发现这是废话!!!如果有未能配对的王子和公主,那么这个王子一定不是公主喜欢的人。
反证法:假如这个王子出现在了公主喜欢的人的列表中,且这个公主没有嫁出去,这个王子也没有娶任何一个公主,那么这个公主和王子就一定可以配对,矛盾。
所以题目这句话有点坑
最后我们的代码就很简洁了:
#include<bits/stdc++.h>
#define endl '\n'//一般输出规模超过10^5最好用'\n'换行
using namespace std;
const int maxn = 100010;
bool used[maxn], choosed[maxn];
//分别为王子和公主
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--)
{
int n;
cin >> n;
fill(used + 1, used + n + 1, false);
fill(choosed + 1, choosed + n + 1, false);
for(int i = 1; i <= n; i++)
{
int k;
cin >> k;
bool flag = false;
for(int j = 1; j <= k; j++)
{
int x;
cin >> x;
if(!flag && !used[x])
{
used[x] = true;
choosed[i] = true;
flag = true;
}
}
}
bool flag = false;
for(int i = 1; i <= n; i++)
if(!used[i])
{
for(int j = 1; j <= n; j++)
if(!choosed[j])
{
cout << "IMPROVE" << endl << j << ' ' << i << endl;
flag = true;
break;
}
if(flag)
break;
}
if(!flag)
cout << "OPTIMAL" << endl;
}
return 0;
}
时间复杂度是
因为只要有一个没配对的王子,就必然有一个没配对的公主。
吐槽下题意翻译,叫王子和公主多好
CF1327C Game with Chips
这里我要感谢下比赛时候的弹窗:
We don't have to minimize the number of operations in problem C.
所以其实这道题的
由于最大移动次数限制是
我的做法是这样的:
首先先从右上角出发,不断向下,走到底再向左走一步,不断向上,走到顶再向左走一步,不断向下……一直走到左下角/左上角。
然后从左下角/左上角出发,与刚才的做法类似,一直走到最右端。
(读者可根据代码理解)
把整个棋盘全部走一遍之后,所有的chip一定能够经过目标。
这是因为我们的操作实际上相当于把所有的chip都利用墙壁堆到了左上角或左下角,然后再带着所有的chip遍历棋盘。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, m, tmp
cin >> n >> m >> tmp;
for(int i = 1; i <= 4 * k; i++)
cin >> tmp;
//大大简化了空间复杂度
string ans = "";
for(int i = 1; i <= m; i++)
{
for(int j = 1; j < n; j++)
if((m - i) % 2 == 0)
ans += 'D';
else
ans += 'U';
if(i != m)
ans += 'L';
}
for(int i = 1; i <= m; i++)
{
for(int j = 1; j < n; j++)
if(i % 2 == 0)
ans += 'D';
else
ans += 'U';
if(i != m)
ans += 'R';
}
cout << ans.size() << endl << ans << endl;
return 0;
}
时间复杂度
CF1327E Count The Blocks
这题其实就是个乘法原理的计算。
不难想到,一个block要么出现在两边,要么出现在中间,分别计算答案即可。
令
首先
然后,如果一个长为
解释:
如果这个block出现在中间,方案总数是
解释:
但是注意:当
由于要大量用到
代码如下:
#include<bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
long long n;
const int maxn = 200010;
long long pow10[maxn], ans[maxn];
int main()
{
cin >> n;
pow10[0] = 1;
for(int i = 1; i <= n; i++)
pow10[i] = pow10[i - 1] * 10 % mod;
ans[n] = 10;
ans[n - 1] = ans[n] * 2 * 9;
for(int i = n - 2; i > 0; i--)
{
ans[i] = (ans[i] + 10 * 9 * pow10[n - i - 1] % mod * 2) % mod;
ans[i] = (ans[i] + 10 * 9 * 9 * pow10[n - i - 2] % mod * (n - i - 1) % mod) % mod;
}
for(int i = 1; i <= n; i++)
cout << ans[i] << ' ';
cout << endl;
return 0;
}
时间复杂度