比赛链接:Here

1560A. Dislike of Threes

找出第 $k$ 大的不可被 $3$ 整除以及非 $3$ 结尾的整数

直接枚举出前 1000 个符合条件的数,然后输出

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. vector<int>a;
  4. int i = 1;
  5. while (a.size() != 1000) {
  6. if (i % 3 != 0 && i % 10 != 3) a.push_back(i);
  7. i += 1;
  8. }
  9. int _; for (cin >> _; _--;) {
  10. int n; cin >> n;
  11. cout << a[n - 1] << "\n";
  12. }
  13. }

1560B. Who’s Opposite?

一些人均匀站成一圈,每人的编号从 $1$ 开始,给定 $a,b,c$ 三个整数,$a,b$ 是通过圆心看向对方,请问是否存在 $c$ 的对位,如果存在则输出相应编号,否则输出 $-1$

Codeforces Round #739 (Div. 3) - 图1

通过样图容易发现对位的编号差的两倍即 Codeforces Round #739 (Div. 3) - 图2 的大小,所以如果 Codeforces Round #739 (Div. 3) - 图3 存在对位的话,肯定是 Codeforces Round #739 (Div. 3) - 图4

当然注意边界

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. int _; for (cin >> _; _--;) {
  4. int a, b, c; cin >> a >> b >> c;
  5. int n = 2 * abs(a - b);
  6. if (a > n || b > n || c > n) {cout << "-1\n"; continue;}
  7. cout << (n / 2 + c - 1) % n + 1 << "\n";
  8. }
  9. }

1560C. Infinity Table

Codeforces Round #739 (Div. 3) - 图5

题意:给定 Codeforces Round #739 (Div. 3) - 图6 请问 Codeforces Round #739 (Div. 3) - 图7 在第几行第几列

好明显的规律题?但赛时没想太多,跑了暴力

  • 先找到第 Codeforces Round #739 (Div. 3) - 图8 行第 Codeforces Round #739 (Div. 3) - 图9 列的数值,然后在第 Codeforces Round #739 (Div. 3) - 图10 行和第 Codeforces Round #739 (Div. 3) - 图11 列上循环跑一下即可
  • 因为 Codeforces Round #739 (Div. 3) - 图12 最多 Codeforces Round #739 (Div. 3) - 图13 行保证不会 TLE
  1. void solve() {
  2. ll x; cin >> x;
  3. ll i = 1;
  4. while (i * i < x) i++;
  5. ll j = i - 1;
  6. ll tmp = x - j * j;
  7. if (tmp <= i) cout << tmp << " " << i << endl;
  8. else {
  9. int t = i * i - x;
  10. cout << i << " " << t + 1 << endl;
  11. }
  12. }

1560D. Make a Power of Two

D题开始搞自己了,

给定一个整数 Codeforces Round #739 (Div. 3) - 图14#card=math&code=n%20%28n%5Cle%2010%5E9%29) 和两种操作,

  • 删除 Codeforces Round #739 (Div. 3) - 图15 的任何一位
  • 在最右边加一位(可以是 Codeforces Round #739 (Div. 3) - 图16 任何一个数)

请问最少的操作数使得 Codeforces Round #739 (Div. 3) - 图17Codeforces Round #739 (Div. 3) - 图18#card=math&code=2%5Ek%280%5Cle%20k%29)


Codeforces Round #739 (Div. 3) - 图19


这很明显 Codeforces Round #739 (Div. 3) - 图20 最大也就 Codeforces Round #739 (Div. 3) - 图21 ,直接枚举了,然后比较原字符串和 Codeforces Round #739 (Div. 3) - 图22 的位数差:Codeforces Round #739 (Div. 3) - 图23Codeforces Round #739 (Div. 3) - 图24 为相同位数个数

相同类型:AcWing 3796. 凑平方

来自群友的详细思路,From 群友d3ac

题目关键信息: 随便删除,只能在右边加,前导零不自动删除

  • 因为要看看到底操作几次就可以变得和Codeforces Round #739 (Div. 3) - 图25#card=math&code=2%5Ek%5C%20%5C%20%280%5Cle%20k%5Cle%2063%29)相等,拿到题我们就先想暴力一点的做法,判断时间复杂度,再考虑优化.所以最暴力的就是直接枚举Codeforces Round #739 (Div. 3) - 图26,再与Codeforces Round #739 (Div. 3) - 图27来作比较,看看需要操作几次
  • 计算时间复杂度:Codeforces Round #739 (Div. 3) - 图28<Codeforces Round #739 (Div. 3) - 图29,所以行.
  • 然后再来考虑怎么把Codeforces Round #739 (Div. 3) - 图30Codeforces Round #739 (Div. 3) - 图31进行比较,来计算需要几个操作,这个其实就是字符串匹配,将Codeforces Round #739 (Div. 3) - 图32来匹配原来的Codeforces Round #739 (Div. 3) - 图33,因为只能从左边添加字符,假设Codeforces Round #739 (Div. 3) - 图34所以Codeforces Round #739 (Div. 3) - 图35中必须是有从Codeforces Round #739 (Div. 3) - 图36Codeforces Round #739 (Div. 3) - 图37连续且有顺序排列的才行,举个例子:Codeforces Round #739 (Div. 3) - 图38,匹配成功了Codeforces Round #739 (Div. 3) - 图39个,Codeforces Round #739 (Div. 3) - 图40,匹配成功Codeforces Round #739 (Div. 3) - 图41个,因为必须要删除完所有的才能加入Codeforces Round #739 (Div. 3) - 图42.
  • 再考虑一点小小的优化和怎么写才好写

    • Codeforces Round #739 (Div. 3) - 图43预处理出来,放在一个数组里面方便每次用,减少时间复杂度.
    • Codeforces Round #739 (Div. 3) - 图44Codeforces Round #739 (Div. 3) - 图45都转换为字符串,方便处理.
  • Codeforces Round #739 (Div. 3) - 图46的字符串下长度为Codeforces Round #739 (Div. 3) - 图47,匹配成功了Codeforces Round #739 (Div. 3) - 图48个(注意,Codeforces Round #739 (Div. 3) - 图49指向的是下一个位置,所以要Codeforces Round #739 (Div. 3) - 图50),当前Codeforces Round #739 (Div. 3) - 图51的长度是Codeforces Round #739 (Div. 3) - 图52.最终的答案就是Codeforces Round #739 (Div. 3) - 图53,其中Codeforces Round #739 (Div. 3) - 图54Codeforces Round #739 (Div. 3) - 图55需要添加的,Codeforces Round #739 (Div. 3) - 图56是需要删除的.

注意:需要枚举到Codeforces Round #739 (Div. 3) - 图57才行

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. int _; for (cin >> _; _--;) {
  4. string s; cin >> s;
  5. int ans = 1e9;
  6. for (int i = 0; i < 64; ++i) {
  7. string t = to_string(1ull << i);
  8. int k = 0;
  9. for (int j = 0; j < int(s.size()); ++j)
  10. if (k < int(t.size()) && s[j] == t[k]) k += 1;
  11. ans = min(ans, int(s.size() + int(t.size()) - 2 * k));
  12. }
  13. cout << ans << '\n';
  14. }
  15. }

1560E. Polycarp and String Transformation

From 群友d3ac

首先思考一下给出的字符串那么长,到底该怎么去分割开,要是分割开,那就爽歪歪.

  • Codeforces Round #739 (Div. 3) - 图58为例子
  • 正常分割Codeforces Round #739 (Div. 3) - 图59

所以不难看到,要想把他分出来还是有点难度的,但是每次会删除一个字符,我们再倒过来看看,先是只有一种字母,然后再是只有两种字符……有全部的字母,所以我们倒序枚举,从字符串的末尾开始向头开始枚举的话,就可以找到删除的顺序,因为后删除的字符肯定在后面还会出现的,而先删除的字符就只会在前面,会后被枚举到,因此,我们找到了删除的顺序

再来考虑原字符串是什么,先这样,我们统计一下每个字母在大字符串出现了多少次,结果是这样的:

Codeforces Round #739 (Div. 3) - 图60,Codeforces Round #739 (Div. 3) - 图61,Codeforces Round #739 (Div. 3) - 图62,Codeforces Round #739 (Div. 3) - 图63,Codeforces Round #739 (Div. 3) - 图64,Codeforces Round #739 (Div. 3) - 图65.

每个字符在每次轮回的时候出现次数都是一样的,在删除了它之前是一个特定值Codeforces Round #739 (Div. 3) - 图66,删除后就是Codeforces Round #739 (Div. 3) - 图67,所以我们将所有的字符出现次数除上它是第几个被删除掉的,结果就是这样了

Codeforces Round #739 (Div. 3) - 图68,Codeforces Round #739 (Div. 3) - 图69,Codeforces Round #739 (Div. 3) - 图70,Codeforces Round #739 (Div. 3) - 图71,Codeforces Round #739 (Div. 3) - 图72,Codeforces Round #739 (Div. 3) - 图73

然而母串,也就是原字符串中,每个字母出现次数也是也么多次.

至此,我们已经求出了字符串和顺序,要考虑Codeforces Round #739 (Div. 3) - 图74就简单了,就是模拟题目所说过程,用我们得到的字符串去看,行不行就好了

注意:要memset 反例:aaabbb

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. int _; for (cin >> _; _--;) {
  4. string t; cin >> t;
  5. reverse(t.begin(), t.end());
  6. map<char, int> freq;
  7. string ord;
  8. for (char c : t) {
  9. if (!freq[c]) ord += c;
  10. freq[c] += 1;
  11. }
  12. int n = int(ord.length());
  13. int len = 0;
  14. for (int i = 0; i < n; ++i) len += freq[ord[i]] / (n - i);
  15. reverse(t.begin(), t.end());
  16. if (len > t.size()) {
  17. cout << "-1\n";
  18. continue;
  19. }
  20. string s = t.substr(0, len);
  21. reverse(ord.begin(), ord.end());
  22. string reals = s;
  23. string fin = "";
  24. for (char c : ord) {
  25. fin += s;
  26. string news ;
  27. for (char d : s)
  28. if (d != c) news += d;
  29. s = news;
  30. }
  31. if (fin == t) cout << reals << " " << ord << "\n";
  32. else cout << "-1\n";
  33. }
  34. }

1560F2. Nearest Beautiful Number (hard version)

翻译一下官方题解(官方题解解释的很清楚,好评)

假设数字 Codeforces Round #739 (Div. 3) - 图75 包含 Codeforces Round #739 (Div. 3) - 图76 位数字,其十进制表示为 Codeforces Round #739 (Div. 3) - 图77。 所需的数字 Codeforces Round #739 (Div. 3) - 图78 不大于由 Codeforces Round #739 (Div. 3) - 图79 个数字 9 组成的数字。这个数字是 1-beautiful,而任何 1-beautiful 数字同时是 k-beautiful,所以 Codeforces Round #739 (Div. 3) - 图80 最多包含 Codeforces Round #739 (Div. 3) - 图81 个数字。 同时,Codeforces Round #739 (Div. 3) - 图82 所以 Codeforces Round #739 (Div. 3) - 图83 至少包含 Codeforces Round #739 (Div. 3) - 图84 位数字。 因此,所需的数字正好包含 Codeforces Round #739 (Div. 3) - 图85 位数字。
因为我们要寻找最小的 Codeforces Round #739 (Div. 3) - 图86,所以我们需要首先最小化第一个数字,然后再最小化第二个数字,等等。因此,我们需要找到 Codeforces Round #739 (Div. 3) - 图87 的十进制表示的前缀,它是十进制表示的前缀的 Codeforces Round #739 (Div. 3) - 图88。 让我们贪心地做吧。

我们找出包含不超过 Codeforces Round #739 (Div. 3) - 图89 个不同数字的 Codeforces Round #739 (Div. 3) - 图90 的最大前缀。 假设前缀的长度为 Codeforces Round #739 (Div. 3) - 图91。 如果 Codeforces Round #739 (Div. 3) - 图92,那么 Codeforces Round #739 (Div. 3) - 图93 已经是 k-beautiful 的了,直接输出即可。 否则,让我们像数字一样将前缀增加 Codeforces Round #739 (Div. 3) - 图94,例如 如果 Codeforces Round #739 (Div. 3) - 图95Codeforces Round #739 (Div. 3) - 图96,那么我们将 Codeforces Round #739 (Div. 3) - 图97Codeforces Round #739 (Div. 3) - 图98,结果前缀为 Codeforces Round #739 (Div. 3) - 图99。所有其他数字 Codeforces Round #739 (Div. 3) - 图100#card=math&code=%28d%7Bp%2B2%7D%2Cd%7Bp%2B3%7D%2C…%2Cd_m%29),让我们设置为零(例如,如果 Codeforces Round #739 (Div. 3) - 图101 并且 Codeforces Round #739 (Div. 3) - 图102,那么 Codeforces Round #739 (Div. 3) - 图103 就会变成 Codeforces Round #739 (Div. 3) - 图104 )。 旧 Codeforces Round #739 (Div. 3) - 图105 的答案就是新 Codeforces Round #739 (Div. 3) - 图106 的答案。 为了得到新 Codeforces Round #739 (Div. 3) - 图107 的答案,让我们再次开始描述的过程来准备新 Codeforces Round #739 (Div. 3) - 图108

具体可以再参考代码理解

  • 时间复杂度:Codeforces Round #739 (Div. 3) - 图109#card=math&code=%5Cmathcal%7BO%7D%28m%5E2%29)
  1. void solve() {
  2. string s;
  3. int k;
  4. cin >> s >> k;
  5. while (true) {
  6. set<char> cs;
  7. for (auto c : s) cs.insert(c);
  8. if (cs.size() <= k) {cout << s << "\n"; return ;}
  9. cs.clear();
  10. int lst = 0;
  11. for (;; lst++) {
  12. cs.insert(s[lst]);
  13. if (cs.size() > k) {
  14. while (s[lst] == '9') lst -= 1;
  15. s[lst]++;
  16. for (int i = lst + 1; i < s.size(); ++i) s[i] = '0';
  17. break;
  18. }
  19. }
  20. }
  21. }

JLY 关于F1的代码:Here