• “蔚来杯“2022牛客暑期多校训练营6


    J. Number Game

    给出A,B,C三个数,每次操作可以把B变为A-B,也可以将C变成B-C,给出x,问经过若干次操作之后能否使得C等于x。

    思路:首先有一个性质可以知道,这个x一定是两种操作交替进行得来的因为如果一个操作连续做两次,相当于没有操作。这样我们可以倒着推:

    在这里我们规定B'=A-B:

    C_{n}=B-C_{n-1}=x

    C_{n-1}=B-C_{n}=B-x

    C_{n-2}=B^{'}-C_{n-1}=B^{'}-B+x

    C_{n-3}=2\times B-B^{'}-x

    根据这些推导,可以知道此时满足条件:(C+x-B)%(B-B')==0,而因为第一步是先改变B的值还是先改变C的值不确定,所以另一种的满足条件即为:(C+x-B')%(B-B')==0。注意特判:当C==x时,不需要进行任何操作;如果A=2*B,即改变B的操作没有任何作用,此时只有B-C==x时才会满足条件。

    AC Code:

    1. #include
    2. int t,A,B,C,x;
    3. int main(){
    4. std::ios::sync_with_stdio(false);
    5. std::cin.tie(0);
    6. std::cout.tie(0);
    7. std::cin>>t;
    8. while(t--){
    9. std::cin>>A>>B>>C>>x;
    10. int BB=A-B;
    11. if(C==x){
    12. std::cout<<"Yes"<<'\n';
    13. continue;
    14. }
    15. if(2*B==A&&B-C==x){
    16. std::cout<<"Yes"<<'\n';
    17. continue;
    18. }
    19. if(2*B==A){
    20. std::cout<<"No"<<'\n';
    21. continue;
    22. }
    23. if((C-x)%(BB-B)==0){
    24. std::cout<<"Yes"<<'\n';
    25. continue;
    26. }
    27. if((C+x-B)%(B-BB)==0||(C+x-BB)%(B-BB)==0){
    28. std::cout<<"Yes"<<'\n';
    29. continue;
    30. }
    31. std::cout<<"No"<<'\n';
    32. }
    33. return 0;
    34. }

    os:签到好难。。

    G. Icon Design

    给出数字n,输出等比例的图像。

    思路:(1)模拟,队友搞的,很强;(2)数据范围小于等于5,直接打表也很不错。

    AC Code:

    1. #include
    2. int n;
    3. void N(int n,int h){
    4. if(h==1||h==2*n+3){
    5. for(int i=1;i<=2*n+3;i++){
    6. if(i==1||i==2*n+3) std::cout<<"@";
    7. else std::cout<<".";
    8. }
    9. }
    10. else{
    11. for(int i=1;i<=2*n+3;i++){
    12. if(i==1||i==2*n+3||i==h) std::cout<<"@";
    13. else std::cout<<".";
    14. }
    15. }
    16. }
    17. void F(int n,int h){
    18. if(h==1||h==n+2){
    19. for(int i=1;i<=2*n+3;i++)
    20. std::cout<<"@";
    21. }
    22. else{
    23. std::cout<<"@";
    24. for(int i=1;i<=2*n+2;i++)
    25. std::cout<<".";
    26. }
    27. }
    28. void L(int n,int h){
    29. if(h==2*n+3){
    30. for(int i=1;i<=2*n+3;i++)
    31. std::cout<<"@";
    32. }
    33. else{
    34. std::cout<<"@";
    35. for(int i=1;i<=2*n+2;i++)
    36. std::cout<<".";
    37. }
    38. }
    39. void S(int n,int h){
    40. if(h==1||h==2*n+3||h==n+2){
    41. for(int i=1;i<=2*n+3;i++)
    42. std::cout<<"@";
    43. }
    44. if(h>1&&h2){
    45. std::cout<<"@";
    46. for(int i=1;i<=2*n+2;i++)
    47. std::cout<<".";
    48. }
    49. if(h>n+2&&h<2*n+3){
    50. for(int i=1;i<=2*n+2;i++)
    51. std::cout<<".";
    52. std::cout<<"@";
    53. }
    54. }
    55. int main(){
    56. std::ios::sync_with_stdio(false);
    57. std::cin.tie(0);
    58. std::cout.tie(0);
    59. std::cin>>n;
    60. for(int i=1;i<=13*n+19;i++)
    61. std::cout<<"*";
    62. std::cout<<'\n';
    63. for(int i=1;i<=n;i++)
    64. for(int j=1;j<=13*n+19;j++){
    65. if(j==1) std::cout<<"*";
    66. else if(j==13*n+19) std::cout<<"*"<<'\n';
    67. else std::cout<<".";
    68. }
    69. for(int i=1;i<=2*n+3;i++)
    70. {
    71. for(int j=1;j<=13*n+19;j++)
    72. {
    73. if(j==1) std::cout<<"*";
    74. else if(j==13*n+19) std::cout<<"*"<<'\n';
    75. else if(j==n+3)
    76. {
    77. N(n,i);
    78. for(int k=1;k<=n+1;k++)
    79. std::cout<<".";
    80. F(n,i);
    81. for(int k=1;k<=n+1;k++)
    82. std::cout<<".";
    83. L(n,i);
    84. for(int k=1;k<=n+1;k++)
    85. std::cout<<".";
    86. S(n,i);
    87. for(int k=1;k<=n+1;k++)
    88. std::cout<<".";
    89. j=13*n+18;
    90. }
    91. else std::cout<<".";
    92. }
    93. }
    94. for(int i=1;i<=n;i++)
    95. for(int j=1;j<=13*n+19;j++){
    96. if(j==1) std::cout<<"*";
    97. else if(j==13*n+19) std::cout<<"*"<<'\n';
    98. else std::cout<<".";
    99. }
    100. for(int i=1;i<=13*n+19;i++)
    101. std::cout<<"*";
    102. std::cout<<'\n';
    103. return 0;
    104. }

     B. Eezie and Pie

     给定一棵树,每个点给出一个权值d[i],表示该位置向1走的这条路径中最多走d[i]步,问每个点可以由几个点到达。

    思路:每个点可以向上走d[i]步,说明这一段每个点的结果都要+1,很显然是个差分问题,将O(n)转化为O(1)修改,然后最后一步DFS统计答案即可,基本是个树上点差分的板子题。

    AC Code:

    1. #include
    2. #define int long long
    3. typedef long long ll;
    4. const int N=2e6+5;
    5. int n,cnt;
    6. int head[N],e[N<<1],next[N<<1],id[N],out[N];
    7. int deep[N],size[N],top[N],fa[N],son[N];
    8. int d[N],fat[N][30],f[N],w[N];
    9. void add_edge(int u,int v){
    10. e[cnt]=v;
    11. next[cnt]=head[u];
    12. head[u]=cnt++;
    13. }
    14. void DFS1(int u,int father){
    15. deep[u]=deep[father]+1;
    16. size[u]=1;
    17. fa[u]=father;
    18. for(int k=1;k<=25;k++){
    19. fat[u][k]=fat[fat[u][k-1]][k-1];
    20. }
    21. for(int i=head[u];~i;i=next[i]){
    22. int j=e[i];
    23. if(j==father) continue;
    24. fat[j][0]=u;
    25. DFS1(j,u);
    26. size[u]+=size[j];
    27. if(size[son[u]]
    28. }
    29. }
    30. void DFS2(int u,int father){
    31. f[u]=w[u];
    32. for(int i=head[u];~i;i=next[i]){
    33. int j=e[i];
    34. if(j==father) continue;
    35. DFS2(j,u);
    36. f[u]+=f[j];
    37. }
    38. }
    39. int LCA(int u,int depth){
    40. for(int k=25;k>=0;k--){
    41. if(deep[fat[u][k]]>=depth)
    42. u=fat[u][k];
    43. }
    44. return u;
    45. }
    46. signed main(){
    47. std::ios::sync_with_stdio(false);
    48. std::cin.tie(0);
    49. std::cout.tie(0);
    50. std::cin>>n;
    51. memset(head,-1,sizeof(head));
    52. for(int i=1;i<=n-1;i++){
    53. int u,v;
    54. std::cin>>u>>v;
    55. add_edge(u,v);
    56. add_edge(v,u);
    57. }
    58. DFS1(1,0);
    59. std::vector<int>d(n+5,0);
    60. for(int i=1;i<=n;i++){
    61. std::cin>>d[i];
    62. }
    63. for(int i=1;i<=n;i++){
    64. int tar=deep[i]-d[i];
    65. tar=std::max((int)1,tar);
    66. int t=LCA(i,tar);
    67. w[fa[t]]--;
    68. w[i]++;
    69. }
    70. DFS2(1,0);
    71. for(int i=1;i<=n;i++){
    72. std::cout<" \n"[i==n];
    73. }
    74. return 0;
    75. }

    os:一开始队友写的暴力,很容易就T了一发,,不打这种比较正式难度的比赛不知道,一打发现原来签到的知识点都没学全呜呜呜

    Z-Game on Grid

    给出一个n*m的棋盘,由'.','a','b'组成,走到a算Alice赢,走到b算Bob赢,走到(n,m)平局,每次每个人可以向右或者向下走一格,Alice先手,问是否有先手必胜,平局或者必输的策略。

    思路:考虑DP。我也不知道为什么,感觉很怪。标解给的是记忆化搜索的做法。即倒着进行DP转移,我们在计算先手必胜时,设定A处值为1,B处为0,(n,m)处为0,根据到某一步是先手还是后手分类讨论,当到达(i,j)点且为先手操作时,只要(i+1,j)或者(i,.j+1)任意一个是先手必胜态则一定会胜;若当前为后手操作时,仅当(i,j+1)和(i+1,j)两点都为先手必胜态才会胜,即表示为符号:

    其他两种情况类似考虑,只是设置不同的初始值即可。

    题解写的很妙,它把状态表示成二进制,即题解中1,2,4分别表示001,010,100三种状态,这样类似状态压缩的方法可以学习。 

    AC Code:

    1. #include
    2. typedef long long ll;
    3. const int N=505;
    4. int t,n,m;
    5. char f[N][N][2];
    6. std::string s[N];
    7. int DFS(int x,int y,int u){
    8. if(s[x][y]=='A') return 1;
    9. if(s[x][y]=='B') return 4;
    10. if(x==n-1&&y==m-1) return f[x][y][u]=2;
    11. char &q=f[x][y][u];
    12. if(q==-1){
    13. if(u==0){
    14. q=0;
    15. if(x+1DFS(x+1,y,u^1);
    16. if(y+1DFS(x,y+1,u^1);
    17. }
    18. else{
    19. q=7;
    20. if(x+1DFS(x+1,y,u^1);
    21. if(y+1DFS(x,y+1,u^1);
    22. }
    23. }
    24. return q;
    25. }
    26. int main(){
    27. std::ios::sync_with_stdio(false);
    28. std::cin.tie(0);
    29. std::cout.tie(0);
    30. std::cin>>t;
    31. while(t--){
    32. std::cin>>n>>m;
    33. for(int i=0;i
    34. std::cin>>s[i];
    35. }
    36. memset(f,-1,sizeof(f));
    37. int ans=DFS(0,0,0);
    38. std::cout<<(ans&1?"yes":"no")<<' '<<(ans&2?"yes":"no")<<' '<<(ans&4?"yes":"no")<<'\n';
    39. }
    40. return 0;
    41. }

    补不动了,就这样吧

  • 相关阅读:
    C++程序入门(helloworld.cpp编写)
    layUI带搜索的选择框样式和官网显示不一致
    重新定义商业——以用户为中心的全新商业模式
    Android13适配-Google官方照片视频选择器
    1186: 奖学金(结构体专题)
    【Matlab】一、解常微分方程ODE
    【学习笔记38】JavaScript中的本地存储
    SpringBoot自动装配
    企业精准拓客必不可少的利器丨快鲸scrm系统
    面试阿里,倒在了第4轮后,才幡然醒悟——论系统学习的重要性
  • 原文地址:https://blog.csdn.net/m0_62289613/article/details/126656074