zoukankan      html  css  js  c++  java
  • Codeforces Round 696(Div.2)


    A、Puzzle From the Future

    题意:

    给两个长度相同的$01$串$a$和$b$,把$a$和$b$做不进位加法,然后结果中连续相同的数字缩成一个数字,设这个数字是$d$。给出$b$,问$d$最大时$a$的情况。

    题解:

    显然不能出现相同连续数字最优,直接根据前一位数字和当前$a_i$和$b_i$能达到的最大情况分情况讨论即可。

    B、Different Divisors

    题意:

    给出$d$,求最小的$a$,使得$a$的因数任意两两之差不小于$d$,且至少有$4$个不同因数。

    题解:

    筛素数,然后$1$肯定选,选出距离$1+d$且大于等于$1+d$的素数$p$,同理找出$q geq 1 + p$,结果就是$p imes q$。

    C、Array Destruction

    题意:

    给一个长度是$2 imes n$的数组,在开始前选一个$x$,每步删除时,先删除数组中任意两个和是$x$的数,然后$x$变成较大的那个数,继续删除,直到所有的数都删完,求删除的策略。

    题解:

    比赛的时候我往$dfs$的方向想了,但是$dfs$是大材小用。首先显然的性质就是,每次删除必选没有删掉的数中最大的那个。此时,除了第一次删,剩下那个数也确定了,但是题目样例$4$中,如果删了$11$之后选$4$和$7$,那么会删不完,选$5$和$6$才能删完,因此$7$就要搭配最大的删掉,但是我们事先并不知道需要删掉这个$7$,只能枚举所有的数组中的非最大值。找有没有两个数加起来等于当前的$x$可以用$multiset$也可以用桶,$multiset$记得删除时删迭代器,删数将导致所有相同的数都会被删掉。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e3 + 5;
     4 
     5 bool multi = 1;
     6 int a[N << 1];
     7 multiset<int> s;
     8 vector<pair<int, int>> v;
     9 
    10 void solve()
    11 {
    12     s.clear();
    13     int n;
    14     scanf("%d", &n);
    15     n <<= 1;
    16     for (int i = 1; i <= n; ++i)
    17         scanf("%d", a + i), s.insert(a[i]);
    18     sort(a + 1, a + n + 1);
    19     for (int i = 1; i < n; ++i)
    20     {
    21         v.clear();
    22         multiset<int> s1 = s;
    23         auto it = s1.find(a[i]);
    24         int t1;
    25         if (it != s1.end())
    26         {
    27             t1 = *it;
    28             s1.erase(it);
    29         }
    30         it = --s1.end();
    31         int cur = *it;
    32         v.push_back({t1, cur});
    33         s1.erase(it);
    34         while (s1.size())
    35         {
    36             int tmp = cur - *(--s1.end());
    37             cur = *(--s1.end());
    38             s1.erase(--s1.end());
    39             it = s1.find(tmp);
    40             if (it != s1.end())
    41             {
    42                 t1 = *it;
    43                 s1.erase(it);
    44                 v.push_back({t1, cur});
    45             }
    46             else
    47                 break;
    48         }
    49         if (s1.size() == 0)
    50         {
    51             printf("YES
    ");
    52             printf("%d
    ", v[0].first + v[0].second);
    53             for (auto &i : v)
    54                 printf("%d %d
    ", i.first, i.second);
    55             return;
    56         }
    57     }
    58     printf("NO
    ");
    59 }
    60 int main()
    61 {
    62     int t;
    63     if (multi)
    64         scanf("%d", &t);
    65     else
    66         t = 1;
    67     while (t--)
    68         solve();
    69     return 0;
    70 }
    View Code

    D、Cleaning

    题意:

    给$n$个数,每次选相邻的两个数都减一,当第$i$堆减到$0$时,第$i-1$和第$i+1$堆也不算是相邻,问在删除前允许交换任意相邻数一次的前提下能不能把所有数归零。

    题解:

    显然的结论,如果所有数都能归零时,从两边开始归零是一定可以的。假设一个序列能归零,则对于左边:$a_2' = a_2 - a_1$,$a_3' = a_3 - a_2' -> a_3 - (a_2 - a_1)$,$a_4' = a_4 - a_3' = a_4 - (a_3 - (a_2 - a_1))$。令$l_i = a_i - a_{i-1}$,意义是$a_i$被$a_{i-1}$删完了之后还剩多少,则$a_i' = a_i - p_{i-1}$,如果$a_i > a_{i+1}$,说明$a_i$必不可能被删完,此时$l_i = -1$,如果$l_{i-1} = -1$,则$l_i = -1$。因为如果是前面删不完,后面的$l_i$没有意义。右边同理。我们发现,交换$a_i$和$a_{i+1}$时,它左边的直到$l_{i-1}$和右边的直到$r_{i+2}$不会受影响,所以只需要判断$a_i,a_{i+1},l_{i-1},r_{i+2}$的关系即可。显然,如果可行,一定有一个位置有$l_i = r_{i+1}$。为了考虑边界,即交换$a_1,a_2$或交换$a_{n-1},a_n$的情况。我们在数组两边个增加一个$l_0 = a_0 = 0,r_{n+1} =  a_{n+1} = 0$。

     AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 2e5 + 5;
     4 typedef long long ll;
     5 
     6 bool multi = 1;
     7 ll a[N], l[N], r[N];
     8 void solve()
     9 {
    10     int n;
    11     scanf("%d", &n);
    12     memset(l, 0, sizeof(l[0]) * (n + 2));
    13     memset(r, 0, sizeof(r[0]) * (n + 2));
    14     a[n + 1] = 0;
    15     for (int i = 1; i <= n; ++i)
    16         scanf("%lld", &a[i]);
    17     l[0] = a[0];
    18     for (int i = 1; i < n + 2; ++i)
    19     {
    20         if (l[i - 1] == -1 || l[i - 1] > a[i])
    21             l[i] = -1;
    22         else
    23             l[i] = a[i] - l[i - 1];
    24     }
    25     r[n + 1] = a[n + 1];
    26     for (int i = n; i >= 0; --i)
    27     {
    28         if (r[i + 1] == -1 || r[i + 1] > a[i])
    29             r[i] = -1;
    30         else
    31             r[i] = a[i] - r[i + 1];
    32     }
    33     for (int i = 0; i < n + 1; ++i)
    34         if (l[i] != -1 && r[i + 1] != -1 && l[i] == r[i + 1])
    35             return void(printf("YES
    "));
    36     for (int i = 1; i < n; ++i)
    37         if (l[i - 1] != -1 && r[i + 2] != -1 && l[i - 1] <= a[i + 1] && r[i + 2] <= a[i] && a[i + 1] - l[i - 1] == a[i] - r[i + 2])
    38             return void(printf("YES
    "));
    39     printf("NO
    ");
    40 }
    41 int main()
    42 {
    43     int t;
    44     if (multi)
    45         scanf("%d", &t);
    46     else
    47         t = 1;
    48     while (t--)
    49         solve();
    50     return 0;
    51 }
    View Code
  • 相关阅读:
    Vim Taglist插件的安装与配置
    static变量和static函数
    Linux线程同步读写锁 rwlock
    Linux top命令 使用详解
    Python学习资料
    记录点滴
    自定义的动态buffer
    【数据存储】【Redis】第七章:Redis缓存Zset类型的使用
    RabbitMQ:第二章:Spring整合RabbitMQ(简单模式,广播模式,路由模式,通配符模式,消息可靠性投递,防止消息丢失,TTL,死信队列,延迟队列,消息积压,消息幂等性)
    RabbitMQ:第三章:Springboot集成RabbitMQ(直连模式,工作队列模式,发布订阅模式,路由模式,通配符模式)
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/14305656.html
Copyright © 2011-2022 走看看