• ShanDong Multi-University Training #3


    Ant colony

    题意大体就是一堆蚂蚁,有个战斗力值,如果某个蚂蚁的战斗力值是某个区间内其他蚂蚁的约数,那么这个蚂蚁就可以流放掉,最后就是问l到r区间内还剩下多少蚂蚁,其实就是一个线段树维护区间问题,维护的信息就是这个区间内的最大公约数、最小值以及最小值的个数,因此如果某个区间内的最大公约数和最小值相同,那么战斗力值等于最小值的蚂蚁都会被流放掉,减去就是剩下的蚂蚁,如果不相同,那区间内所有蚂蚁都是剩下的

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. int a[100010];
    5. struct node {
    6. int gd, minn, cnt;
    7. };
    8. node Segtree[100010 << 2];
    9. int gcd(int a, int b) {
    10. return b == 0 ? a : gcd(b, a % b);
    11. }
    12. node merge(node a, node b) {
    13. node c;
    14. c.gd = gcd(a.gd, b.gd);
    15. c.minn = min(a.minn, b.minn);
    16. if (a.minn == b.minn) {
    17. c.cnt = a.cnt + b.cnt;
    18. }
    19. else if (a.minn < b.minn) {
    20. c.cnt = a.cnt;
    21. }
    22. else {
    23. c.cnt = b.cnt;
    24. }
    25. return c;
    26. }
    27. inline void buildtree(int i, int l, int r) {
    28. if (l == r) {
    29. Segtree[i].gd = Segtree[i].minn = a[l];
    30. Segtree[i].cnt = 1;
    31. return;
    32. }
    33. int mid = l + r >> 1;
    34. buildtree(i << 1, l, mid);
    35. buildtree(i << 1 | 1, mid + 1, r);
    36. Segtree[i] = merge(Segtree[i << 1], Segtree[i << 1 | 1]);
    37. }
    38. node query(int i, int l, int r, int x, int y) {
    39. if (l > y || r < x) {
    40. return {0, (int)1e9, 0};
    41. }
    42. if (l >= x && r <= y) {
    43. return Segtree[i];
    44. }
    45. int mid = l + r >> 1;
    46. return merge(query(i << 1, l, mid, x, y), query(i << 1 | 1, mid + 1, r, x, y));
    47. }
    48. int main() {
    49. ios::sync_with_stdio(false);
    50. cin.tie(nullptr);
    51. int n, q;
    52. cin >> n;
    53. for (int i = 1; i <= n; i++) {
    54. cin >> a[i];
    55. }
    56. buildtree(1, 1, n);
    57. cin >> q;
    58. while (q--) {
    59. int l, r;
    60. cin >> l >> r;
    61. node c = query(1, 1, n, l, r);
    62. if (c.minn == c.gd) {
    63. cout << r - l + 1 - c.cnt << '\n';
    64. }
    65. else {
    66. cout << r - l + 1 << '\n';
    67. }
    68. }
    69. return 0;
    70. }

    New String

    重新定义a到z的字典序,然后按照新定义排序,问第k小的字符串

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. map<char, int> mp;
    5. bool cmp(string a, string b) {
    6. int len1 = a.size(), len2 = b.size();
    7. for (int i = 0; i < min(len1, len2); i++) {
    8. if (mp[a[i]] < mp[b[i]]) {
    9. return true;
    10. }
    11. else if (mp[a[i]] > mp[b[i]]) {
    12. return false;
    13. }
    14. }
    15. if (len1 > len2) {
    16. return false;
    17. }
    18. else if (len1 < len2) {
    19. return true;
    20. }
    21. else {
    22. return true;
    23. }
    24. }
    25. int main() {
    26. ios::sync_with_stdio(false);
    27. cin.tie(nullptr);
    28. string s;
    29. cin >> s;
    30. int n, k;
    31. cin >> n;
    32. vector<string> a(n);
    33. for (int i = 0; i < n; i++) {
    34. cin >> a[i];
    35. }
    36. cin >> k;
    37. k--;
    38. for (int i = 0; i < 26; i++) {
    39. mp[s[i]] = i;
    40. }
    41. sort(a.begin(), a.end(), cmp);
    42. cout << a[k] << '\n';
    43. return 0;
    44. }

    Problem - E - Codeforces

    题意大体是一张图里有a,b两个点,'.'可以走,'*'不可以走,每一秒a和b做相同的动作,问a和b能否相遇,如果相遇就输出最小步数,这样就bfs搜索+记录步数,注意边界问题以及下一个如果是'*‘原地不动,a和b的坐标相等就输出步数

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. int n;
    5. string mp[55];
    6. bool vis[55][55][55][55];
    7. struct node {
    8. int xa, xb, ya, yb, cnt;
    9. };
    10. int mov[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
    11. queue<node> qu;
    12. int main() {
    13. ios::sync_with_stdio(false);
    14. cin.tie(nullptr);
    15. cin >> n;
    16. for (int i = 0; i < n; i++) {
    17. cin >> mp[i];
    18. }
    19. node now;
    20. for (int i = 0; i < n; i++) {
    21. for (int j = 0; j < n; j++) {
    22. if (mp[i][j] == 'a') {
    23. now.xa = i;
    24. now.ya = j;
    25. mp[i][j] = '.';
    26. }
    27. if (mp[i][j] == 'b') {
    28. now.xb = i;
    29. now.yb = j;
    30. mp[i][j] = '.';
    31. }
    32. }
    33. }
    34. now.cnt = 0;
    35. vis[now.xa][now.ya][now.xb][now.yb] = true;
    36. qu.push(now);
    37. while (!qu.empty()) {
    38. node nxt;
    39. nxt = now = qu.front();
    40. qu.pop();
    41. if (now.xa == now.xb && now.ya == now.yb) {
    42. cout << now.cnt << '\n';
    43. return 0;
    44. }
    45. now.cnt = nxt.cnt + 1;
    46. for (int i = 0; i < 4; i++) {
    47. now.xa = nxt.xa + mov[i][0];
    48. now.ya = nxt.ya + mov[i][1];
    49. now.xb = nxt.xb + mov[i][0];
    50. now.yb = nxt.yb + mov[i][1];
    51. if (now.xa >= 0 && now.ya >= 0 && now.xa < n && now.ya < n && mp[now.xa][now.ya] == '.') {
    52. }
    53. else {
    54. now.xa = nxt.xa;
    55. now.ya = nxt.ya;
    56. }
    57. if (now.xb >= 0 && now.yb >= 0 && now.xb < n && now.yb < n && mp[now.xb][now.yb] == '.') {
    58. }
    59. else {
    60. now.xb = nxt.xb;
    61. now.yb = nxt.yb;
    62. }
    63. if (!vis[now.xa][now.ya][now.xb][now.yb]) {
    64. vis[now.xa][now.ya][now.xb][now.yb] = true;
    65. qu.push(now);
    66. }
    67. }
    68. }
    69. cout << "no solution\n";
    70. return 0;
    71. }

    Maximum Value

    题意就是求ai%aj的最大值,其中ai要大于等于aj,那先保证序列有序的情况下,如果直接遍历会TLE,这里考虑二分找最大可能值,可知ai大于等于aj,那么ai=n*aj+mod,因此,最大可能值一定出现在n倍和n+1倍之间最后一个值,直接lower_bound二分得到n+1倍的第一个值,它的前一个就是要找的最大可能值

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. int main() {
    4. ios::sync_with_stdio(false);
    5. cin.tie(nullptr);
    6. int n;
    7. cin >> n;
    8. vector<int> a(n);
    9. for (int i = 0; i < n; i++) {
    10. cin >> a[i];
    11. }
    12. sort(a.begin(), a.end());
    13. int ans = 0;
    14. for (int i = 0; i < n; i++) {
    15. if (a[i] != a[i + 1] && i + 1 < n) {
    16. int x = lower_bound(a.begin(), a.end(), 2 * a[i]) - a.begin();
    17. for (int j = 2; j * a[i] <= a[n - 1]; j++) {
    18. x = lower_bound(a.begin(), a.end(), j * a[i]) - a.begin();
    19. ans = max(ans, a[x - 1] % a[i]);
    20. }
    21. ans = max(ans, a[n - 1] % a[i]);
    22. ans = max(ans, a[x - 1] % a[i]);
    23. }
    24. }
    25. cout << ans << '\n';
    26. return 0;
    27. }

    Prefix Equality

    判断集合a和集合b的前缀是否相等,集合哈希即可

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. const i64 mod = 1e9 + 7;
    5. i64 n, q;
    6. i64 a[200010], b[200010];
    7. set<i64> se;
    8. int main() {
    9. ios::sync_with_stdio(false);
    10. cin.tie(nullptr);
    11. cin >> n;
    12. i64 s = 0;
    13. for (int i = 1; i <= n; i++) {
    14. i64 x;
    15. cin >> x;
    16. if (se.find(x) == se.end()) {
    17. s = (s + x * (x + 137) % mod * (x + 997) % mod) % mod;
    18. }
    19. a[i] = s;
    20. se.insert(x);
    21. }
    22. se.clear();
    23. s = 0;
    24. for (int i = 1; i <= n; i++) {
    25. i64 x;
    26. cin >> x;
    27. if (se.find(x) == se.end()) {
    28. s = (s + x * (x + 137) % mod * (x + 997) % mod) % mod;
    29. }
    30. b[i] = s;
    31. se.insert(x);
    32. }
    33. cin >> q;
    34. while (q--) {
    35. int x, y;
    36. cin >> x >> y;
    37. if (a[x] == b[y]) {
    38. cout << "Yes\n";
    39. }
    40. else {
    41. cout << "No\n";
    42. }
    43. }
    44. return 0;
    45. }

    Problem - H - Codeforces

    线性dp,可以发现手中的金币数量最大值是非常小的,求最小的步行距离就是求最大的骑行距离,那就可以提前处理出我当次花费多少钱能走到的最远距离,每次肯定是选取最远的那个车站,这样就不需要额外考虑最后一个车站和总路程的关系,因为骑行一定是在两个车站之间,不可能就一个车站以至于走不到下一个车站就到终点了

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. int dp[1000010][6];
    5. int a[1000010];
    6. int main() {
    7. ios::sync_with_stdio(false);
    8. cin.tie(nullptr);
    9. int n, p, s;
    10. cin >> n >> p >> s;
    11. for (int i = 1; i <= n; i++) {
    12. cin >> a[i];
    13. }
    14. int k;
    15. cin >> k;
    16. int ans = 0;
    17. for (int i = 1; i <= n; i++) {
    18. for (int j = 0; j <= k; j++) {
    19. dp[i][j] = max(dp[i][j], dp[i - 1][j]);
    20. ans = max(ans, dp[i][j]);
    21. for (int l = 1; l + j <= k; l++) {
    22. int dis = l * s + a[i];
    23. int now = upper_bound(a + 1, a + 1 + n, dis) - a;
    24. now--;
    25. dp[now][l + j] = max(dp[now][l + j], dp[i][j] + a[now] - a[i]);
    26. if (dis > a[n]) {
    27. break;
    28. }
    29. }
    30. }
    31. }
    32. cout << p - ans << '\n';
    33. return 0;
    34. }

    250-like Number

    埃式筛筛出所有质数,然后暴力求和即可

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. using u64 = unsigned long long;
    5. #define M 10000000
    6. int cnt = 0;
    7. i64 a[M + 5];
    8. bool is_prime[M + 5];
    9. void init(){
    10. is_prime[0] = is_prime[1] = false;
    11. for (int i = 2; i <= M; i++) {
    12. if (is_prime[i]) {
    13. a[++cnt] = i;
    14. for (int j = 2; j * i <= M; j++) {
    15. is_prime[i * j] = false;
    16. }
    17. }
    18. }
    19. }
    20. int main() {
    21. ios::sync_with_stdio(false);
    22. cin.tie(nullptr);
    23. memset(is_prime, true, sizeof(is_prime));
    24. i64 n, ans = 0;
    25. init();
    26. cin >> n;
    27. for (int i = 1; i <= cnt; i++) {
    28. for (int j = i + 1; j <= cnt; j++) {
    29. if (a[j] * a[j] > n / a[i] / a[j]) {
    30. break;
    31. }
    32. ans++;
    33. }
    34. }
    35. cout << ans << "\n";
    36. return 0;
    37. }

    Endless Walk

    问有多少个点不是通向环的,反向图+拓扑排序,图反着建,入度为0的一定是不能通向环的,因为正图一定是只有入度没有出度,反图才能只有出度没有入度的,这样的点一定不可以,然后根据这些点进行拓扑排序,从它走向的所有的其他的入度为0的也一定都是不能通向环的点

    AC代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. using i64 = long long;
    4. vector<int> G[200010];
    5. int main() {
    6. ios::sync_with_stdio(false);
    7. cin.tie(nullptr);
    8. int n, m;
    9. cin >> n >> m;
    10. vector<int> deg(n + 1);
    11. for (int i = 0; i < m; i++) {
    12. int u, v;
    13. cin >> u >> v;
    14. G[v].push_back(u);
    15. deg[u]++;
    16. }
    17. queue<int> qu;
    18. for (int i = 1; i <= n; i++) {
    19. if (deg[i] == 0) {
    20. qu.push(i);
    21. }
    22. }
    23. int ans = n;
    24. while (!qu.empty()) {
    25. int u = qu.front();
    26. qu.pop();
    27. ans--;
    28. for (auto it : G[u]) {
    29. if (--deg[it] == 0) {
    30. qu.push(it);
    31. }
    32. }
    33. }
    34. cout << ans << '\n';
    35. return 0;
    36. }

  • 相关阅读:
    springboot球类运动教学网站的设计与实现271611
    TcpServerChannel 类服务
    一本专业130+总分400+上海交通大学819考研经验上交电子信息与通信工程上岸,真题,大纲,参考书。
    计算机毕业设计php+vue基于微信小程序的房屋租赁小程序
    (十二) 共享模型之无锁【原子整数、原子引用、原子数组】
    【软件测试】(北京)字节跳动科技有限公司二面笔试题
    初识Java 14-1 测试
    线性规划学习
    Windows开启监控
    java计算机毕业设计销售人员绩效管理系统源码+系统+数据库+lw文档(1)
  • 原文地址:https://blog.csdn.net/eyuhaobanga/article/details/125523118