每日水题记录(洛谷 10 月)

每日水题记录(洛谷 10 月)

只记录红橙题,因为 \(\ge\) 橙不算很水的题。

\(2023.11.9\)

P1012 [NOIP1998 提高组] 拼数

\(75\) 分代码

直接把每个数字用字符串输入,然后按字典序排序。

原因:不能直接按字典序排序,寄。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 22, kInf = (((1 << 30) - 1) << 1) + 1;

int n;
string s[kMaxN];

int main() {
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; ++ i) {
    cin >> s[i];
  }
  sort(s + 1, s + n + 1);
  for (int i = n; i >= 1; -- i) {
    cout << s[i];
  }
  return 0;
}

\(100\) 分代码

我们直接用自己秘制的全比排序(注:这是以前写的,语言会有点那啥),每次比较 \(2\) 个数 \(a, b\),如果 \(a + b > b + a\),则交换 \(a, b\)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 22, kInf = (((1 << 30) - 1) << 1) + 1;

int n;
string s[kMaxN];

bool cmp(string a, string b) {
  return a + b > b + a;
}

int main() {
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; ++ i) {
    cin >> s[i];
  }
  for (int i = 1; i <= n; ++ i) {
    for (int j = i + 1; j <= n; ++ j) {
      if (cmp(s[i], s[j])) {
        swap(s[i], s[j]);
      }
    }
  }
  for (int i = n; i >= 1; -- i) {
    cout << s[i];
  }
  return 0;
}

当然,还有 \(O(n \log n)\) 的快速排序。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 22, kInf = (((1 << 30) - 1) << 1) + 1;

int n;
string s[kMaxN];

bool cmp(string a, string b) {
  return a + b > b + a;
}

int main() {
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; ++ i) {
    cin >> s[i];
  }
  sort(s + 1, s + n + 1, cmp);
  for (int i = 1; i <= n; ++ i) {
    cout << s[i];
  }
  return 0;
}

P1017 [NOIP2000 提高组] 进制转换

前置知识:被除数 \(=\)\(\times\) 除数 \(+\) 余数。

在 C++ 中,会出现这样的问题:

我:\(-10 \bmod -3 = 1\),C++ 系统:\(-10 \bmod -3 = -1\)

所以,用短除法。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = -1, kInf = (((1 << 30) - 1) << 1) + 1;

int n, m;

void S1(int n) {
  if (n < 10) {
    cout << n;
  } else {
    cout << char('A' + n - 10);
  }
}

void S2(int n, int m) {
  if (n == 0) {
    return;
  }
  if (!(n % m) || n > 0) {
    S2(n / m, m);
    S1(n % m);
  } else {
    S2(n / m + 1, m);
    S1(-m + n % m);
  }
}

int main() {
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);
//  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  cout << n << "=";
  S2(n, m);
  cout << "(base" << m << ")\n";
  return 0;
}

\(2023.11.10\)

B3647【模板】Floyd

经典模板题。

状态转移方程:\(f_{i, j} = min(f_{i, j}, f_{i, k} + f_{k, j})\),时间复杂度 \(O(n^3)\)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 110, kInf = (((1 << 30) - 1) << 1) + 1;

int n, m, f[kMaxN][kMaxN];

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
  cin >> n >> m;
  memset(f, 0x3f, sizeof f);
  for (int i = 1, u, v, w; i <= m; ++ i) {
    cin >> u >> v >> w;
    f[u][v] = w;
    f[v][u] = w;
  }
  for (int i = 1; i <= n; ++ i) {
    f[i][i] = 0;
  }
  for (int k = 1; k <= n; ++ k) {
    for (int i = 1; i <= n; ++ i) {
      for (int j = 1; j <= n; ++ j) {
        (f[i][j] > f[i][k] + f[k][j]) && (f[i][j] = f[i][k] + f[k][j]);
      }
    }
  }
  for (int i = 1; i <= n; ++ i) {
    for (int j = 1; j <= n; ++ j) {
      cout << f[i][j] << ' ';
    }
    cout << '\n';
  }
  return 0;
}

当然,你还可以用 \(O(n \log m)\) 的 dijkstra,\(O(nk)\) 的 SPFA(关于 SPFA,它死了)……

B3648 [语言月赛202208] 你几岁了

输入输出题。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = -1, kInf = (((1 << 30) - 1) << 1) + 1;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
  int x;
  cin >> x;
  cout << "I am " << x << " years old.\n";
  return 0;
}

B3649 [语言月赛202208] 大小比较

条件分支题。

这里可以用三目运算符,格式为 条件? 分支 1 : 分支 2

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = -1, kInf = (((1 << 30) - 1) << 1) + 1;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
  int a, b;
  cin >> a >> b;
  cout << (a <= b? "YE5" : "N0") << '\n';
  return 0;
}

B3650 [语言月赛202208] 求和

循环题。

定义一个 \(ans\),每次把 \(ans\)\(i\ (1 \le i \le n)\),然后输出。

注意,本题轻微卡常。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = -1, kInf = (((1 << 30) - 1) << 1) + 1;

ll n, ans = 0;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
  cin >> n;
  for (int i = 1; i <= n; ++ i) {
    ans += i;
    cout << ans << '\n';
  }
  return 0;
}

\(2023.11.11\)

B3821 [语言月赛 202308] 小粉兔 Failed System Test

摘自我的题解:

problem 1

我们注意到,\(1 \le n \le 10^9\),而 \(k\) 可能等于 \(n\),所以 \(k\) 也可能是 \(10^9\),代码中有 \(k \times 3\) 的运算,而 \(10^9 \times 3 = 3 \times 10^9\),又 \(3 \times 10^9 > 2^{31} - 1\),所以只要让 \(k = 10^9\) 即可。

problem 2

我们注意到,这个代码运行完 \(18\)\(19\) 行后,只判断了 c,没有判断 b 存在,所以我们输出只满足 \(2\)\(3\) 条件的字符串即可。(例:aacc

#include <iostream>

using namespace std;

int main() {
  int taskId;
  cin >> taskId;
  if (taskId == 1) {
    cout << "1000000000 999999999" <<endl;
  } else if (taskId == 2) {
    cout << "aaaccc" << endl;
  } else { // 这个 else 不会被执行
    cout << "I AK IOI! You AK NOI!" << endl;
  }
}

\(2023.10.12\)

无,但是送给大家一个东西。

任何题目,从暴力开始。

\(2023.10.13\)

无。

\(2023.10.14\)

B3632 集合运算 1

只要懂得集合的基本运算即可。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 77, kInf = (((1 << 30) - 1) << 1) + 1, kL = 63;

int n, m, a[kMaxN], b[kMaxN];

int main() {
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
	for (int i = 1, x; i <= n; ++ i) {
    cin >> x;
		a[x] = 1;
	}
	cin >> m;
	for (int i = 1, x; i <= m; ++ i) {
    cin >> x;
		b[x] = 1;
	}
	cout << n << '\n';
	for (int i = 0; i <= kL; ++ i) {
    if (a[i] && b[i]) {
			cout << i << " ";
		}
	}
	cout << '\n';
	for (int i = 0; i <= kL; ++ i) {
    if (a[i] || b[i]) {
			cout << i << " ";
		}
	}
	cout << '\n';
  return 0;
}

B3637 最长上升子序列

模板题。

初始 \(f_i = 1\),当 \(a_j > a_i\)\(f_j = max(f_j, f_i + 1)\),答案为 \(\max_{i = 1}^{n} f_i\)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

const int kMaxN = 5050, kInf = (((1 << 30) - 1) << 1) + 1;

int n, a[kMaxN], f[kMaxN];

int main() {
  cin >> n;
  for (int i = 1; i <= n; ++ i) {
    cin >> a[i];
    f[i] = 1;
  }
  for (int i = 1; i <= n; ++ i) {
    for (int j = i + 1; j <= n; ++ j) {
      if (a[j] > a[i]) {
        f[j] = max(f[j], f[i] + 1);
      }
    }
  }
  int ans = 0;
  for (int i = 1; i <= n; ++ i) {
    ans = max(ans, f[i]);
  }
  cout << ans << '\n';
  return 0;
}

B3636 文字工作

很简单,\(f_0 = f_1 = 0\),转移方程 \(f_i = min(f_{i - 1} + 1,\ f_{i \div 2} + 1)\)\(f_{i + 1} = f_i + 1\)

时间复杂度 \(O(n \div 2)\)

dp 写法(以前写的):

#include<bits/stdc++.h>
using namespace std;
#define qwq ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
int n, dp[1000010];

int main()
{
	qwq;
	cin >> n;
	dp[0] = dp[1] = 0;
	for (int i = 2; i <= n; i += 2)
	{
		dp[i] = min(dp[i-1] + 1, dp[i/2] + 1);
		dp[i+1] = dp[i] + 1;
	}
	cout << dp[n];
	return 0;
} 
  • 循环写法:

时间复杂度 \(O(\log n)\)

\(n \bmod 2 = 0\),则 \(n\) 除以 \(2\),否则 \(n\)\(1\)。每次答案 \(+1\)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = -1, kInf = (((1 << 30) - 1) << 1) + 1;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  ll n, ans = 0;
  for (cin >> n; n != 1; (n % 2 == 0? n >>= 1 : n -= 1), ++ ans);
  cout << ans << '\n';
  return 0;
}

\(2023.10.15\)

CF1789A Serval and Mocha's Array

我们只需要找到存在一组 \((i, j)\) 使得 \(1 \le i < j \le n\)\(\gcd(a_i, a_j) = 2\) 就为 Yes,因为前面两个需要最大公约数 \(< 2\),因为如果前两个最大公约数 \(< 2\),那么长度 \(> 2\) 的前缀的最大公约数永远不会 \(> 2\)。这里就不太细讲了,请自行思考。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 110, kInf = (((1 << 30) - 1) << 1) + 1;

int n, a[kMaxN];
bool f = 0;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int t;
  for (cin >> t; t; -- t) {
    f = 0;
    cin >> n;
    for (int i = 1; i <= n; ++ i) {
      cin >> a[i];
    }
    for (int i = 1; i <= n; ++ i) {
      for (int j = i + 1; j <= n; ++ j) {
        if (__gcd(a[i], a[j]) <= 2) {
          f = 1;
        }
      }
    } 
    cout << (f == 1? "Yes" : "No") << '\n';
  }
  return 0;
}

CF1789B Serval and Inversion Magic

考试时写的,写的什么玩意\oh。自己尝试理解一下吧。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 130, kInf = (((1 << 30) - 1) << 1) + 1;

int n, a[kMaxN], sum = 0;
string s;
bool f = 1, ff = 1, fff = 1;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int t;
  for (cin >> t; t; -- t) {
    f = 1, ff = 1, fff = 1;
    cin >> n >> s;
    int i = 0, j = n - 1;
    for (; i <= j; ++ i, -- j) {
      if (s[i] != s[j] && !ff) {
        cout << "NO\n";
        fff = 0;
        break;
      }
      if (s[i] != s[j]) {
        f = 0;
      }
      if (s[i] == s[j] && !f) {
        ff = 0;
      }
    }
    (fff) && (cout << "YES\n");
  }
  return 0;
}

CF1883B Chemistry

设字符出现个数为奇数的个数为 \(sum\),当 \(n - k = 1\) 时(只留一个字母)或 \(sum - 1 \le k\) 即为 YES,否则 NO

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

using ll = long long;

const int kMaxN = 130, kInf = (((1 << 30) - 1) << 1) + 1;

int n, a[kMaxN], k, sum = 0;
string s;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int t;
  for (cin >> t; t; -- t) {
    cin >> n >> k >> s;
    memset(a, 0, sizeof a);
    for (int i = 0; i < n; ++ i) {
      ++ a[s[i]];
    }
    sum = 0;
    for (int i = 'a'; i <= 'z'; ++ i) {
      sum += a[i] % 2;
    }
    -- sum;
    if (n - k == 1) {
      cout << "Yes\n";
    } else if (sum <= k) {
      cout << "Yes\n";
    } else {
      cout << "No\n";
    }
  }
  return 0;
}

to be update.

posted @ 2023-11-09 20:32  beautiful_chicken233  阅读(267)  评论(0)    收藏  举报