• Codeforces Round #814 (Div. 2)


    目录

    A. Chip Game(博弈)

    B. Mathematical Circus

    C. Fighting Tournament

    D1.D2. Burenka and Traditions


    A. Chip Game(博弈)

    题意:给你了n*m的格子,Tonya和Burenka从左下角出发,两人只能走奇数长度的路.假设两人足够聪明我们如何能够,不能走了的就失败(只能往右或者往上走).

    思路:已知我们直接把从左往右和从下往上两条路进行分割,当这两条路为奇数长度可以把它们分成1,否则分成2(因为写一个人改变上一个人的奇偶性,所以奇数相当于上一个人走一步,偶数为两个人都走一步).

    1. #include
    2. #define int long long
    3. using namespace std;
    4. const int N =5e5+10,mod=998244353;
    5. void solve()
    6. {
    7. int n,m;
    8. cin>>n>>m;
    9. if(n%2==m%2)
    10. cout<<"Tonya"<
    11. else
    12. cout<<"Burenka"<
    13. return ;
    14. }
    15. signed main()
    16. {
    17. cin.tie(0);
    18. cout.tie(0);
    19. ios::sync_with_stdio(0);
    20. int t;
    21. cin>>t;
    22. while(t--)
    23. solve();
    24. return 0;
    25. }

    B. Mathematical Circus

    题意:我们有一个偶数长度n的数组,还有一个k,我们要把数组分成n/2对.每对为(a,b),并且满足(a+k)*b被4整除.问是否可以构造出.

    思路:

    1.当k为奇数时,已知奇数+奇数=偶数.偶数拥有因子2,两个偶数相乘至少有2个因子2,肯定能被4整除,所以这种情况就之就输出(奇数,偶数)搭配即可.

    2.当k为偶数时,我们发现如果含有一个偶数%4=0那么这一组就确定了,(奇数,4的倍数).那么还剩下2的倍数和其他奇数,显然奇数+偶数还是奇数,所以我们要在2的倍数上下功夫.当k不是2的倍数的情况下,(k+2的倍数)肯定是4的倍数.如果k是4的倍数就无法成立.

    1. #include
    2. #define int long long
    3. using namespace std;
    4. const int N =2e5+10,mod=998244353;
    5. int a[N],b[N];
    6. void solve()
    7. {
    8. int n,k;
    9. cin>>n>>k;
    10. if(k%2)
    11. {
    12. int f=0;
    13. for(int i=1;i<=n/2;i++)
    14. {
    15. a[i]=i*2-1;
    16. b[i]=i*2;
    17. }
    18. for(int i=1;i<=n/2;i++)
    19. {
    20. if((a[i]+k)*b[i]%4)
    21. {
    22. f=1;
    23. break;
    24. }
    25. }
    26. if(f)
    27. cout<<"NO"<
    28. else
    29. {
    30. cout<<"YES"<
    31. for(int i=1;i<=n/2;i++)
    32. cout<" "<
    33. }
    34. }
    35. else
    36. {
    37. int f=0;
    38. if(k%4)
    39. {
    40. for(int i=1;i<=n/2;i++)
    41. {
    42. if((i*2)%4)
    43. {
    44. a[i]=i*2;
    45. b[i]=i*2-1;
    46. }
    47. else
    48. {
    49. a[i]=i*2-1;
    50. b[i]=i*2;
    51. }
    52. }
    53. for(int i=1;i<=n/2;i++)
    54. {
    55. if((a[i]+k)*b[i]%4)
    56. {
    57. f=1;
    58. break;
    59. }
    60. }
    61. if(f)
    62. cout<<"NO"<
    63. else
    64. {
    65. cout<<"YES"<
    66. for(int i=1;i<=n/2;i++)
    67. cout<" "<
    68. }
    69. }
    70. else
    71. cout<<"NO"<
    72. }
    73. return ;
    74. }
    75. signed main()
    76. {
    77. cin.tie(0);
    78. cout.tie(0);
    79. ios::sync_with_stdio(0);
    80. int t;
    81. cin>>t;
    82. while(t--)
    83. solve();
    84. return 0;
    85. }

    C. Fighting Tournament

    问题:有n个运动员,q次询问,每次询问包含两个数i,k.意为询问第i位运动员在进行k场比赛的时候会胜利多少场.(比赛规则是取队列前两个队员比赛,胜利者放回队伍前端,失败者在队伍后端)

    思路:我们知道,有一个武力值最高的运动员,如果他开始了比赛,俺么后面无论如何比赛他都会一直在队伍的首位并且一直胜利.所以我们先跑一遍循环,对于每个运动员第一次和最后一次胜利进行处理得出来.然后分情况讨论:

    1.当当前运动员在最强运动员后面,或者比赛根本比不到他,或者他第一次胜利的场次>k,或者根本没有胜利过的话,这个询问就是直接输出0.

    2.当询问的人就是最强运动员时,直接输出k+1-他第一次胜利的场次

    3.生育情况直接输出min(k,f[i].second)-f[i].first+1,也就是最后一次胜利和第一次胜利的场次之间共赢了多少场即可.

    1. #include
    2. #define int long long
    3. using namespace std;
    4. typedef pair<int,int> PII;
    5. const int N =1e5+10,mod=998244353;
    6. int a[N];
    7. void solve()
    8. {
    9. int n,q,maxid=1;
    10. cin>>n>>q;
    11. for(int i=1;i<=n;i++)
    12. {
    13. cin>>a[i];
    14. if(a[i]>a[maxid])
    15. maxid=i;
    16. }
    17. vectorf(n+1);
    18. int sheng=a[1];
    19. int pos=1;
    20. for(int i=2;i<=n;i++)
    21. {
    22. if(a[i]
    23. {
    24. if(f[pos].second==0)
    25. f[pos].first=i-1;
    26. f[pos].second=i-1;
    27. }
    28. else if(a[i]>sheng)
    29. {
    30. sheng=a[i];
    31. pos=i;
    32. f[pos].first=i-1;
    33. f[pos].second=i-1;
    34. }
    35. }
    36. int i,k;
    37. while(q--)
    38. {
    39. cin>>i>>k;
    40. if(i>maxid||k-1||f[i].first>k||f[i].first==0)
    41. cout<<"0"<
    42. else if(i==maxid)
    43. cout<1-f[i].first<
    44. else
    45. cout<<min(k,f[i].second)-f[i].first+1<
    46. }
    47. }
    48. signed main()
    49. {
    50. cin.tie(0);
    51. cout.tie(0);
    52. ios::sync_with_stdio(0);
    53. int t;
    54. cin>>t;
    55. while(t--)
    56. solve();
    57. return 0;
    58. }

    D1.D2. Burenka and Traditions

    问题:有一个长为n的数组,我们每次可以选择一个l,r和任意一个x然后花费(l-r+1)/2(向上取整)的能量去让[l,r]之间的数组元素都异或上x,问最少花费多少能量可以把整个数组所有元素化为0.

    思路:我们可以贪心的去变化,花费一点能量把遍历位置前一位的数移动到下一位去,例如[1,2,4]变化之后就是[0,3,4]->[0,0,7],用一个f数组记录此时的花费为多少,用一个map记录一下移动之后a[i]的位置在哪里.如果我在进行a[i]的变化之后,a[i]在之前出现过(map判断)那么这一个区间异或和就为0,那么我们直接进行f的状态转移f[i]=max(f[i],f[map[a[i]]]+区间长度).当他为0我们就可以直接往下进行操作而不是把这一位转移到下一位了.

    1. #include
    2. #define int long long
    3. using namespace std;
    4. const int N =5e5+10,mod=998244353;
    5. int a[N];
    6. int f[N];
    7. void solve()
    8. {
    9. map<int,int>ma;
    10. int n;
    11. cin>>n;
    12. ma[0]=0;
    13. f[0]=0;
    14. for(int i=1;i<=n;i++)
    15. cin>>a[i];
    16. for(int i=1;i<=n;i++)
    17. {
    18. a[i]^=a[i-1];
    19. f[i]=f[i-1]+1;
    20. if(ma.count(a[i]))
    21. {
    22. f[i]=min(f[i],f[ma[a[i]]]+i-ma[a[i]]-1);
    23. }
    24. ma[a[i]]=i;
    25. }
    26. cout<
    27. return ;
    28. }
    29. signed main()
    30. {
    31. cin.tie(0);
    32. cout.tie(0);
    33. ios::sync_with_stdio(0);
    34. int t;
    35. cin>>t;
    36. while(t--)
    37. solve();
    38. return 0;
    39. }

  • 相关阅读:
    Windows下x86和x64平台的Inline Hook介绍
    CentOS 7 手动安装OpenStack
    pulsar开启mqtt和认证
    Campus SNS 校园社区后端接口开发(附前端地址)
    类和对象
    Java基础知识【HashMap和Hashtable区别与红黑树】
    SAP PP初阶之工单里的主数据
    【AGC】如何集成华为AGC性能管理- iOS
    肠道菌群失调与炎症性肠病的关联
    javaWeb的概念、Web的资源分类、常见的Web服务器
  • 原文地址:https://blog.csdn.net/qq_49593247/article/details/126667082