Good Bye 2019

Posted lanly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Good Bye 2019相关的知识,希望对你有一定的参考价值。

A. Card Game (CF 1270 A)

题目大意

两个人各持有(k_1)(k_2)张牌,牌序号唯一且在范围(1)~(n)其中(n=k_1+k_2)。一次操作两个各亮出一张牌,谁牌序号大,谁拿对方的牌,最后没牌者输,问先手是否必赢。

解题思路

很显然谁持有最大牌谁赢......

但是(tourist)能在一分钟内读完题并敲好代码提交过了真是太强了。


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int n,k1,k2;

int main(void) {
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int kase; read(kase);
    for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        read(n);
        read(k1);
        read(k2);
        bool qwq=false;
        for(int u,i=1;i<=k1;++i){
            read(u);
            if (u==n) qwq=true;
        }
        for(int u,i=1;i<=k2;++i){
            read(u);
        }
        if (qwq) printf("YES
");
        else printf("NO
");
    }
    return 0;
}



B. Interesting Subarray (CF 1270 B)

题目大意

给定一个长度为(n)的数组(a),问是否存在某个区间([l,r]),有(max-mingeq k),其中(max=maxlimits_{i in [l,r]}(a_i))(min=minlimits_{i in [l,r]}(a_i))(k=r-l+1),存在则输出(YES)并输出任意一个符合要求的区间,否则输出(NO).

解题思路

我们考虑一个符合题目条件的区间([l,r]),其中最大值和最小值在端点处是最优的选择,不失一般性,我们设最大值在(r)处,最小值在(l)处,则(max-min=(max_1-max_2)+(max_2-max_3)+...+(max_{k-1}-max_k)=geq k),从中我们可以看出至少有一个(max_i-max_{i+1}>1),才能有该不等式成立,那也一定有至少一个位置(i)(abs(a_i-a_{i+1})geq 2)才行。


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int n,u,v;

int main(void) {
    //ios::sync_with_stdio(false);
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int kase; read(kase);
    for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        read(n);
        read(u);
        bool qwq=false;
        int l=0;
        for(int i=2;i<=n;++i){
            read(v);
            if (ABS(v-u)>1) {qwq=true;l=i-1;}
            u=v;
        }
        if (qwq) printf("YES
%d %d
",l,l+1);
        else printf("NO
");
    }
    return 0;
}



C. Make Good (CF 1270 C)

题目大意

给定(n)个正整数,设(n)个数的和为(sum),异或为(x),若(sum=2x)则这个序列是(good)的,如果不是(good),最多可增加三个正整数,使得这个序列变成(good),求添加数的个数以及数的大小。

解题思路

首先(sum)一定要是偶数,否则我们先加一个数(1),然后再考虑(sum)(x)大小。

注意到异或两次同一个数相当于不变,那么如果(sum<2x),那么我们只要再增加两个同样的数(qwq=dfrac{2x-sum}{2}),这样(x)不变,而(sum)也变成了(2x)

如果(sum>2x),我们再一开始增加一个超大超大的数,让(sum<2x)即可,由于(sumleq 10^{15}),那我们就增加一个(10^{16})的数,即(2^{50}),如果(sum)是奇数,就加(2^{50}+1),然后根据上面的情况即可。

对应代码为注释部分。

这题还有另一种加法,即加两个数(x)(sum+x),这样和就变成(2(sum+x)),异或值变成(sum+x),这样也符合题意。


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    //ios::sync_with_stdio(false);
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int kase; read(kase);
    for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        int n;
        LL sum,xx,u,a;
        read(n);
        sum=xx=0;
        for(int i=1;i<=n;++i){
            read(u);
            sum+=u;
            xx=xx^u;
        }
        printf("2
%lld %lld
",xx,xx+sum);
        /* if ((xx<<1ll)==sum) printf("0

");
        else{
            a=(1ll<<50ll);
            if (sum&1ll) a=a|1ll;
            sum+=a;
            xx=(xx^a);
            xx<<=1;
            LL qwq=xx-sum;
            printf("3
%lld %lld %lld
",a,(qwq>>1),(qwq>>1));
        } */
    }
    return 0;
}



D. Strange Device (CF 1270 D)

题目大意

交互题。

给定(n)(k),以及一个你并不知道长度为(n)的数俩俩不同的数列和(m),每次你可以问(k)个互不相同的下标,对方会告诉你这些下标对应的值里,从小到大排列第(m)个小数的位置和值。不能问多于(n)次。最后你的程序要猜出(m)值。

解题思路

一开始妄图想找到(k)个数然后问它们一波得到(m)值结果不可行。然后妄图用并查集维护每个数在(m)的左边还是右边发现数太多了不可控(qwq)所以我们要考虑少点的数,比如就前(k+1)个数,每次我们选这其中的(k)个数,相当于把其中的一个数从(k+1)个数中剔除,然后我们考虑这个剔除的数对第(m)个数的影响。

假设在这(k+1)个数中,第(m)个数的值为(a),则如果剔除的一个数(i)小于等于(a),则第(m)个数会变成另一个数(b),如果大于(a),则第(m)个数还是(a)。纵观我们剔除(k+1)次的结果,可以知道数(a)会出现(k+1-m次),而数(b)会出现(m)次,于是我们统计较大的数出现的次数就是答案(m)


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    //ios::sync_with_stdio(false);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int n,k;
    read(n);
    read(k);
    vector<bool> sign(k+2,false);
    int ma=0,cnt=0;
    for(int i=1;i<=k+1;++i){
        sign[i]=true;
        sign[i-1]=false;
        printf("? ");
        for(int j=1;j<=k+1;++j) if (!sign[j]) printf("%d ",j);
        puts("");
        fflush(stdout);
        int u,v;
        read(u);read(v);
        if (ma<v){cnt=1;ma=v;}else if (ma==v) ++cnt;
    }
    printf("! %d
",cnt);
    fflush(stdout);
    return 0;
}



May 2020 will be the year of high ratings for the hard workers.





以上是关于Good Bye 2019的主要内容,如果未能解决你的问题,请参考以下文章

Good Bye 2019 C. Make Good

Good Bye 2019

Good Bye 2019 C. Make Good (异或的使用)

Good Bye 2019 A. Card Game

?Good Bye 2019 B. Interesting Subarray

Good Bye 2019 A~G题解