• 第五届传智杯-初赛【A组-题解】


    B题:

    题目背景

    【 题目背景和题目描述的两个题面是完全等价的,您可以选择阅读其中一部分。】

    专攻超统一物理学的莲子,对机械结构的运动颇有了解。如下图所示,是一个三进制加法计算器的(超简化)示意图。

    初始时齿轮的状态如上。

     

    把第一个齿轮拨动一个单位长度,变为如上图所示。 

     

     题解:

    模拟题。按照题目要求输入整数 a,b,模拟这个奇怪的进位规则即可。

    参考代码 

     版本 1:

    1. #include
    2. #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    3. #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    4. using namespace std;
    5. typedef long long i64;
    6. const int INF = 2147483647;
    7. int qread(){
    8. int w=1,c,ret;
    9. while((c = getchar()) > '9' || c < '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    10. while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    11. return ret * w;
    12. }
    13. const int MAXN = 2e5 + 3;
    14. int A[MAXN], B[MAXN];
    15. int main(){
    16. int n = qread(), m = qread(), l = max(n, m);
    17. dn(n, 1, i) A[i] = qread();
    18. dn(m, 1, i) B[i] = qread();
    19. up(1, l, i) A[i] += B[i], A[i + 1] += A[i] / (i + 1), A[i] %= i + 1;
    20. if(A[l + 1]) ++ l;
    21. dn(l, 1, i) printf("%d%c", A[i], " \n"[i == 1]);
    22. return 0;
    23. }

    版本2:

    1. #include
    2. using namespace std;
    3. int a[200050],b[200050];
    4. int main()
    5. {
    6. auto read=([&]{
    7. int x;cin >> x;
    8. return x;
    9. });
    10. int n=read(),m=read();
    11. int len=max(n,m)+1;
    12. generate_n(a+1,n,read);
    13. generate_n(b+1,m,read);
    14. reverse(a+1,a+n+1);
    15. reverse(b+1,b+m+1);
    16. for (int i=1;i<=len;i++)
    17. {
    18. a[i]+=b[i];
    19. a[i+1]+=(a[i]/(i+1));
    20. a[i]%=(i+1);
    21. }
    22. while (a[len]==0 && len>1)
    23. len--;
    24. reverse(a+1,a+len+1);
    25. for (int i=1;i<=len;i++)
    26. cout << a[i] << " ";
    27. return 0;
    28. }

    版本3:

    1. import java.util.Scanner;
    2. public class Main {
    3. public static int[] a = new int[200005];
    4. public static int[] b = new int[200005];
    5. public static int[] c = new int[200005];
    6. public static void main(String[] args) {
    7. Scanner scanner = new Scanner(System.in);
    8. int n = scanner.nextInt(), m = scanner.nextInt();
    9. int maxLength = Math.max(n, m);
    10. for (int i = (maxLength - n) + 1; i <= maxLength; ++i)
    11. a[i] = scanner.nextInt();
    12. for (int i = (maxLength - m) + 1; i <= maxLength; ++i)
    13. b[i] = scanner.nextInt();
    14. for (int i = maxLength, cnt = 2; i > 0; --i, ++cnt) {
    15. c[i] += a[i] + b[i];
    16. if (c[i] >= cnt) {
    17. c[i] -= cnt;
    18. c[i - 1] += 1;
    19. }
    20. }
    21. if (c[0] > 0) {
    22. System.out.printf("%d ", c[0]);
    23. }
    24. for (int i = 1; i <= maxLength; ++i) {
    25. System.out.printf("%d ", c[i]);
    26. }
    27. System.out.println();
    28. }
    29. }

    C题

    题目背景

    你现在不能休息,周围有 deadline 在游荡。

    莲子正在赶自己的程序设计作业。除了完成程序代码的编写,对提交上去的作业进行排版以对助教留下良好印象同样重要。

    而众所周知,文章里面的代码和一些特殊性质的文本是要附上行号的,然而它们的篇幅往往都很长,手动去加容易出现失误。因此,莲子决定自力更生造轮子,写一个行号生成器。

     

    输入格式

    输入包含若干行,为原始的文本文件。

    输出格式

    输出包含若干行,为加上行号后的文本文件。

    输入输出样例

    题解:

    参考代码 

    版本1:

    1. #include<bits/stdc++.h>
    2. #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    3. #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    4. using namespace std;
    5. typedef long long i64;
    6. const int INF = 2147483647;
    7. const int MAXN= 2e4 + 3;
    8. char S[MAXN], c; int l, m;
    9. int main(){
    10. m = count(S + 1 , S + 1 + fread(S + 1, 1, MAXN, stdin), '\n');
    11. int s = log10(m) + 1 + 1e-9, p = 0;
    12. up(1, m, i){
    13. int t = log10(i) + 1 + 1e-9;
    14. for(int j = 1;j <= s - t;++ j) putchar( ' '); printf("%d ", i);
    15. for(p = p + 1;S[p] != 10;++ p) putchar(S[p]); putchar('\n');
    16. }
    17. return 0;
    18. }

    版本2:

    1. #include <iostream>
    2. #include <cstdio>
    3. #include <vector>
    4. using namespace std;
    5. char buf[200050];
    6. vector <char> s[200050];
    7. int cnt;
    8. int get_digit(int x)
    9. {
    10. int digit=1,ret=1;
    11. while (ret<=x)
    12. {
    13. digit++;
    14. ret*=10;
    15. }
    16. return digit;
    17. }
    18. int main()
    19. {
    20. while(fgets(buf,200000,stdin)!=NULL)
    21. {
    22. cnt++;
    23. for (int i=0;buf[i]!='\n';i++)
    24. s[cnt].push_back(buf[i]);
    25. }
    26. int cnt_digit=get_digit(cnt);
    27. for (int i=1;i<=cnt;i++)
    28. {
    29. for (int j=1;j<=cnt_digit-get_digit(i);j++)
    30. putchar(' ');
    31. cout << i << ' ';
    32. for (int j=0;j<s[i].size();j++)
    33. putchar(s[i][j]);
    34. putchar('\n');
    35. }
    36. return 0;
    37. }

    版本3: 

    1. import java.util.Scanner;
    2. import java.util.List;
    3. import java.util.ArrayList;
    4. public class Main {
    5. public static List<String> list = new ArrayList<>();
    6. public static int getBit(int x) {
    7. int cnt = 0;
    8. while (x > 0) {
    9. x /= 10;
    10. ++cnt;
    11. }
    12. return cnt;
    13. }
    14. public static void main(String[] args) {
    15. Scanner scanner = new Scanner(System.in);
    16. while (scanner.hasNextLine()) {
    17. list.add(scanner.nextLine());
    18. }
    19. int size = list.size();
    20. int len = getBit(size);
    21. for (int i = 0; i < size; ++i) {
    22. System.out.printf("%" + len + "d %s\n", i + 1, list.get(i));
    23. }
    24. }
    25. }

     

    D题

    题目背景

    莲子正在研究分子的运动。

    每个分子都有一个速度,约定正方向为正,负方向为负。分子的数量极多,速度又并不一致,看上去杂乱无章。于是莲子希望调整部分分子的速度,使得最终分子们看上去整齐。

     题解:

    参考代码 

    版本1:

    1. #include
    2. #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    3. #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    4. using namespace std;
    5. typedef long long i64;
    6. const int INF = 2147483647;
    7. int qread(){
    8. int w=1,c,ret;
    9. while((c = getchar()) > '9' || c < '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    10. while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    11. return ret * w;
    12. }
    13. const int MAXN = 1e5 + 3;
    14. int A[MAXN], ans = INF;
    15. int main(){
    16. int n = qread(), m = qread();
    17. up(1, n, i) A[i] = qread();
    18. sort(A + 1, A + 1 + n);
    19. int j = 1;
    20. up(1, min(n, m + 1), i){
    21. j = max(i, j);
    22. while((i - 1) + (n - j) + min(i - 1, n - j) > m) ++ j;
    23. ans = min(ans, A[j] - A[i]);
    24. }
    25. printf("%d\n", ans);
    26. return 0;
    27. }

    版本2:

    1. import java.util.Scanner;
    2. import java.util.Arrays;
    3. public class Main {
    4. public static int[] a = new int[100005];
    5. public static void main(String[] args) {
    6. Scanner scanner = new Scanner(System.in);
    7. int n = scanner.nextInt(), m = scanner.nextInt();
    8. for (int i = 1; i <= n; ++i)
    9. a[i] = scanner.nextInt();
    10. Arrays.sort(a, 1, n + 1);
    11. int j = 1, ans = Integer.MAX_VALUE;
    12. for (int i = 1; i <= Math.min(n, m + 1); ++i) {
    13. j = Math.max(j, i);
    14. while((i - 1) + (n - j) + Math.min(i - 1, n - j) > m)
    15. ++j;
    16. ans = Math.min(ans, a[j] - a[i]);
    17. }
    18. System.out.println(ans);
    19. }
    20. }

    F题

    作为大学生,莲子和梅莉有着比高中时更为闲暇的课余时光。在没有课的时候,她们喜欢玩大富翁这一游戏,在游玩过程中交流自己的喜怒哀乐。

     输入输出样例

     

    题解

    模拟题。没什么好说的。这里就讲几个细节:

    参考代码 

     版本1:

    1. #include<bits/stdc++.h>
    2. #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    3. #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    4. using namespace std;
    5. typedef long long i64;
    6. const int INF = 2147483647;
    7. int qread(){
    8. int w=1,c,ret;
    9. while((c = getchar()) > '9' || c < '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    10. while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    11. return ret * w;
    12. }
    13. int n, m, q, maxl; bool o = 1;
    14. const int MAXN = 100 + 3;
    15. int C[MAXN][MAXN], A[MAXN], D[MAXN], L[MAXN], O[3], T[MAXN];
    16. i64 M[2];
    17. int main(){
    18. n = qread(), m = qread(), q = qread(), maxl = qread();
    19. M[0] = M[1] = m, O[0] = O[1] = 1;
    20. up(1, n, i) L[i] = 0, T[i] = -1;
    21. up(1, n, i)
    22. up(0, maxl - 1, j) C[i][j] = qread();
    23. up(1, n, i) D[i] = qread();
    24. for(int op, k;~scanf("%d%d", &op, &k);){
    25. if(op == 1){
    26. if(o == 1){
    27. up(1, n, i) if(T[i] != -1) M[T[i]] += D[i];
    28. }
    29. o ^= 1;
    30. up(1, k, i){
    31. O[o] = (O[o]) % n + 1;
    32. int p = O[o];
    33. if(T[p] == o) M[o] += A[p]; else
    34. if(T[p] == !o){
    35. M[!o] += A[p], M[o] -= A[p];
    36. if(M[o] < 0)
    37. puts(o ? "Merry" : "Renko"), exit(0);
    38. }
    39. }
    40. } else {
    41. int p = O[o];
    42. while(k && L[p] < maxl && M[o] >= C[p][L[p]] && T[p] != !o){
    43. A[p] += C[p][L[p]], M[o] -= C[p][L[p]];
    44. ++ L[p], T[p] = o, -- k;
    45. }
    46. }
    47. }
    48. up(1, n, i) if(T[i] != -1) M[T[i]] += D[i];
    49. printf("%lld %lld\n", M[0], M[1]);
    50. return 0;
    51. }

    版本2:

    1. #include <iostream>
    2. #include <cstdio>
    3. #include <cstring>
    4. #include <algorithm>
    5. #include <cmath>
    6. #include <cctype>
    7. #include <queue>
    8. using namespace std;
    9. inline int read()
    10. {
    11. int x=0,f=1;char ch=getchar();
    12. while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    13. while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    14. return x*f;
    15. }
    16. int n,m,q,L,C[105][105],d[105],a[105],lv[105],pos[2],belong[105];
    17. long long money[2];
    18. const string name[2]={"Renko","Merry"};
    19. inline void putfail(int id)
    20. {
    21. cout << name[id] << endl;
    22. exit(0);
    23. }
    24. inline void forward(int id,int k)
    25. {
    26. for (int i=1;i<=k;i++)
    27. {
    28. int &p=pos[id];
    29. p++;
    30. if (p>n)
    31. p-=n;
    32. if (belong[p]==id)
    33. money[id]+=a[p];
    34. else if (belong[p]==(id^1))
    35. {
    36. money[id]-=a[p];
    37. money[id^1]+=a[p];
    38. }
    39. if (money[id]<0)
    40. putfail(id);
    41. }
    42. }
    43. inline void build(int id,int k)
    44. {
    45. int p=pos[id],cost=C[p][lv[p]];
    46. for (int i=1;(money[id]>=cost && lv[p]<L && (belong[p]==-1 || belong[p]==id) && i<=k);i++)
    47. {
    48. belong[p]=id;
    49. money[id]-=cost;
    50. a[p]+=cost;
    51. cost=C[p][++lv[p]];
    52. }
    53. }
    54. int main()
    55. {
    56. n=read(),m=read(),q=read(),L=read();
    57. for (int i=1;i<=n;i++)
    58. {
    59. for (int j=0;j<L;j++)
    60. C[i][j]=read();
    61. }
    62. for (int i=1;i<=n;i++)
    63. d[i]=read();
    64. pos[0]=pos[1]=1;
    65. fill(belong+1,belong+n+1,-1);
    66. money[0]=money[1]=m;
    67. for (int i=0;i<2*q;i++)
    68. {
    69. int op=read();
    70. begin:
    71. for (int j=1;j<=n && !(i&1);j++)
    72. {
    73. if (belong[j]==0)
    74. money[0]+=d[j];
    75. else if (belong[j]==1)
    76. money[1]+=d[j];
    77. }
    78. int k=read();
    79. forward(i&1,k);
    80. if (i==2*q-1)
    81. break;
    82. op=read();
    83. if (op==1)
    84. {
    85. i++;
    86. goto begin;
    87. }
    88. else
    89. {
    90. k=read();
    91. build(i&1,k);
    92. }
    93. }
    94. for (int j=1;j<=n;j++)
    95. {
    96. if (belong[j]==0)
    97. money[0]+=d[j];
    98. else if (belong[j]==1)
    99. money[1]+=d[j];
    100. }
    101. cout << money[0] << " " << money[1] << endl;
    102. return 0;
    103. }

    G题

    题目背景

    梅莉买到了一张特殊的带有花纹的纸。整张纸的图案可以视为,由一个较小的图案,沿着横向与纵向无限循环而成。同时,这个基本图案部分透明,部分不透明。

    于是,如果将这张纸覆盖在书本上,那么一些字可以被看见,另一些字看不见。

    莲子突发奇想:假使她制作一张很大很大的数表,将花纹纸覆盖在上面,那么就会有很多数字被遮挡。那些没有被遮挡的数字的和是多少呢?

    题目描述

     

     

     

     

     题解:

     参考代码:

    1. #include
    2. #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    3. #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    4. using namespace std;
    5. typedef long long i64;
    6. const int INF = 2147483647;
    7. int n, m, r, c, q;
    8. int qread(){
    9. int w=1,c,ret;
    10. while((c = getchar()) > '9' || c < '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    11. while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    12. return ret * w;
    13. }
    14. const int MAXN = 2e3 + 3;
    15. const int MAXM = 50 + 3;
    16. const int MOD = 998244353;
    17. int A[MAXN][MAXN], S[MAXN][MAXN]; bool B[MAXN][MAXN];
    18. int calc(int a1, int b1, int a2, int b2){
    19. int ret = S[a2][b2];
    20. if(a1 > r) ret = (ret - S[a1 - r][b2] + MOD) % MOD;
    21. if(b1 > c) ret = (ret - S[a2][b1 - c] + MOD) % MOD;
    22. if(a1 > r && b1 > c) ret = (ret + S[a1 - r][b1 - c]) % MOD;
    23. return ret;
    24. }
    25. int main(){
    26. n = qread(), m = qread();
    27. up(1, n, i) up(1, m, j) A[i][j] = qread();
    28. r = qread(), c = qread();
    29. up(1, r, i) up(1, c, j) B[i][j] = qread();
    30. up(1, n, i) up(1, m, j){
    31. S[i][j] = A[i][j];
    32. if(i > r) S[i][j] = (S[i][j] + S[i - r][j]) % MOD;
    33. if(j > c) S[i][j] = (S[i][j] + S[i][j - c]) % MOD;
    34. if(i > r && j > c)
    35. S[i][j] = (S[i][j] - S[i - r][j - c] + MOD) % MOD;
    36. }
    37. q = qread();
    38. up(1, q, i){
    39. int _x1 = qread(), _y1 = qread();
    40. int _x2 = qread(), _y2 = qread();
    41. int ans = 0;
    42. up(1, min(r, _x2 - _x1 + 1), a)
    43. up(1, min(c, _y2 - _y1 + 1), b) if(B[a][b] == 0){
    44. int a1 = _x1 + a - 1, a2 = a1 + (_x2 - a1) / r * r;
    45. int b1 = _y1 + b - 1, b2 = b1 + (_y2 - b1) / c * c;
    46. ans = (ans + calc(a1, b1, a2, b2)) % MOD;
    47. }
    48. printf("%d\n", ans);
    49. }
    50. return 0;
    51. }

    I题

    学校正在组织宴会。

    莲子和梅莉发现,学校的结构十分复杂。学生之间存在着部门与上司的关系。每一个部门内部,都呈现出连成一条线的上司关系。一个部门内等级最高的学生,又可能受限于另外某个部门内的某个学生。

    莲子和梅莉同样参加了宴会。但是她们对参加学生有自己的评判。例如,她对某些部门比较喜欢,对另一些部门则不感兴趣。同时对位居不同等级的学生同样有着不同的看法。

    正如某个经典问题所描述的一样,每个学生都不希望与自己的直接上司共同参加宴会。

    梅莉想要知道,最好情况下,有多少个参加宴会的学生是她喜欢的。

     题目描述

     

     

     

     题解:

     压轴题。

     

    参考代码 

     

    1. #include<bits/stdc++.h>
    2. #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    3. #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    4. using namespace std;
    5. typedef long long i64;
    6. const i64 INF = 1e18;
    7. int n;
    8. int qread(){
    9. int w=1,c,ret;
    10. while((c = getchar()) > '9' || c < '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    11. while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    12. return ret * w;
    13. }
    14. const int MAXN = 1e6 + 3;
    15. const int MAXM = 2e6 + 3;
    16. int R[MAXN], C[MAXN], A[MAXN], F[MAXN], G[MAXM], W[MAXM], o = 0;
    17. int X[MAXM]; i64 U[MAXM][4];
    18. int Y[MAXM]; i64 V[MAXM][4];
    19. int P0[MAXN], Q0[MAXN], P1[MAXN], Q1[MAXN];
    20. int value(int w){return w % 2 == 1 ? w / 2 + 1 : w / 2;}
    21. void calc(int l, int r, i64 &w, bool t){ // [l, r] 区间
    22. if(r - l + 1 == 0){w = 0 ; return;}
    23. if(r - l + 1 == -1){w = 0 ; return;}
    24. if(r - l + 1 == -2){w = -INF; return;}
    25. if(t == false){
    26. int u = min(Q0[l], r); w = P0[r] - P0[u] + ( R[l] == 1 ? value(u - l + 1) : 0);
    27. } else {
    28. int u = min(Q1[l], r); w = P1[r] - P1[u] + (!R[l] == 1 ? value(u - l + 1) : 0);
    29. }
    30. }
    31. void calc(int l, int r, i64 O[4], bool t){ // [l + (0~1), r - (0~1)] 区间
    32. calc(l , r , O[0b11], t);
    33. calc(l , r - 1, O[0b10], t);
    34. calc(l + 1, r , O[0b01], t);
    35. calc(l + 1, r - 1, O[0b00], t);
    36. }
    37. i64 I[MAXM], J[MAXM]; // I 是必须选上,J 是必须不选
    38. void dfs(int u){
    39. if(X[u] == 0) I[u] = W[u], J[u] = 0; else {
    40. int l = X[u], r = Y[u]; dfs(l), dfs(r);
    41. I[u] = W[u]
    42. + max(U[u][0b00] + I[l], U[u][0b01] + J[l])
    43. + max(V[u][0b00] + I[r], V[u][0b01] + J[r]);
    44. J[u] =
    45. + max(U[u][0b10] + I[l], U[u][0b11] + J[l])
    46. + max(V[u][0b10] + I[r], V[u][0b11] + J[r]);
    47. }
    48. }
    49. int main(){
    50. n = qread();
    51. up(1, n, i) R[i] = qread();
    52. up(1, n, i) C[i] = qread();
    53. up(2, n, i) A[i] = qread();
    54. P0[1] = R[1], P1[1] = !R[1];
    55. up(2, n, i){
    56. P0[i] = max(P0[i - 1], P0[i - 2] + R[i]);
    57. P1[i] = max(P1[i - 1], P1[i - 2] + !R[i]);
    58. }
    59. Q0[n] = Q1[n] = n;
    60. dn(n - 1, 1, i){
    61. if( R[i] == 0) Q0[i] = i; else
    62. if( R[i + 1] == 0) Q0[i] = i; else Q0[i] = Q0[i + 1];
    63. if(!R[i] == 0) Q1[i] = i; else
    64. if(!R[i + 1] == 0) Q1[i] = i; else Q1[i] = Q1[i + 1];
    65. }
    66. up(1, n - 1, i){
    67. int t = A[i + 1], f = F[t]; // (i, t) 是特殊点
    68. F[t] = F[i + 1] = ++ o; // 给特殊点分配编号
    69. if(f)
    70. if(X[f]) Y[f] = o, calc(G[f] + 1, i - 1, V[f], C[t]);
    71. else X[f] = o, calc(G[f] + 1, i - 1, U[f], C[t]);
    72. W[o] = R[i] ^ C[t], G[o] = i;
    73. }
    74. up(1, n, i){ // 最后一层都是特殊点
    75. int t = i, f = F[t]; ++ o, W[o] = R[n] ^ C[i];
    76. if(f)
    77. if(X[f]) Y[f] = o, calc(G[f] + 1, n - 1, V[f], C[t]);
    78. else X[f] = o, calc(G[f] + 1, n - 1, U[f], C[t]);
    79. }
    80. dfs(1); printf("%lld\n", max(I[1], J[1]));
    81. return 0;
    82. }

    💖 喜欢我的文章,记得点赞👍+评论💬+收藏⭐️+关注😙の,你的反馈就是我不断更新的动力!

  • 相关阅读:
    MySQL进阶
    基于LSTM-Adaboost的电力负荷预测(Matlab代码实现)
    ChatGPT基本原理
    【云原生】这么火,你不来了解下?
    归并排序详解(递归+非递归)
    【电商数仓】修改压缩编码、hive环境部署、yarn配置、idea开发环境搭建、准备数据
    大学生游戏静态HTML网页设计 (HTML+CSS+JS仿英雄联盟网站15页)
    Stream流式处理
    【Python】Java工程师学Python之PyCharm安装详细教程
    ps2022 - ps to dxf
  • 原文地址:https://blog.csdn.net/weixin_51563198/article/details/128058555