zoukankan      html  css  js  c++  java
  • 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),这样也符合题意。

    还有最优的只用加一个数的方法(如果(sum eq x))
    即先(x=2*x)后,从低位到高位逐一比较(sum)(x)的每一位是否相等,如果不相等则添一个在该位为(1)的数,添这个数后只会影响(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); //两个数
            /* 
            一个数
            xx<<=1;
            LL ans=0;
            int id=0;
            while(sum||xx){
                if ((sum^xx)&1){
                    ans+=(1ll<<id);
                    sum++;
                    xx^=2;
                }
                sum>>=1;
                xx>>=1;
                ++id;
            }
            if (ans) printf("1
    %lld
    ",ans);
            else printf("0
    
    "); 
            */
            /* 
            三个数        
            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;
    }
    


    E. Divide Points (CF 1270 E)

    题目大意

    给出(n)个点坐标,要求将它们分成两个非空集(A)(B),使得没有同组的点距离与不同组的点距离相同。

    解题思路

    由于(n)不大,一开始想着枚举所有距离然后排序,把有相同距离的点对分到同一个组,然后构造了两个反例(qwq),一个是所有点分布呈以一个点为圆心的圆上,另一个是两个圆emmmmm。

    我们试着根据点的坐标性质进行分类,所有点坐标在(mod 2)的意义下我们可以分成四类:((0,0) (0,1) (1,0) (1,1)),如果我们对于属于同类的点都放在一个集合里时,它们的(x)(y)坐标差一定是偶数,这样它们的距离的平方就一定是偶数,这启示我们,如果不同组的点距离的平方是奇数的话,那么就一定没有同组的点距离与不同组的点距离相同。经过分析我们可以知道,点坐标属于((0,0))((1,1))的点与点坐标属于((1,0))((0,1))的点的距离一定是奇数。那么我们就把点坐标属于((0,0))((1,1))放在(A),点坐标属于((1,0))((0,1))放在(B)即可。再综合一下就是点坐标和是偶数的放在(A),点坐标和是奇数的放在(B)

    那要是没有点坐标和是奇数或偶数的怎么办?我们先选定一个点为原点进行整体平移,这样就一定有坐标和为偶数的点。如果没有坐标和是奇数点的话,此时所有点坐标和都为偶数,但我们注意到,如果点属于((0,0))的,它们点的距离的平方是(4)的倍数,而点属于((1,1))的,它们点的距离的平方除以4会余2,这样我们就把((0,0))放在(A)((1,1))放在(B)即可。若没有((1,1))的点的话,我们对全部坐标都除以(2),这样所有点的距离的平方都会除以(4),但该相等的还是相等,不相等的还是不相等,不影响我们的判断。由于坐标最大不超过(10^6),故除以(2)的次数不会超过(log_2 10^6),重复以上操作即可。

    神奇的代码
    #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); cin.tie(0); cout.tie(0);
        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;
        read(n);
        vector<int>x,y;
        for(int u,v,i=0;i<n;++i){
            read(u);read(v);
            x.push_back(u);
            y.push_back(v);
        }
        for(int i=1;i<n;++i){
            x[i]-=x[0];
            y[i]-=y[0];
        }
        x[0]=y[0]=0;
        while(1){
            vector<int> qwq;
            for(int i=1;i<n;++i) 
                if ((x[i]+y[i])&1) qwq.push_back(i);
            if (!qwq.empty()){
                printf("%d
    ",(int)qwq.size());
                for(int i:qwq){
                    printf("%d ",i+1);
                }
                puts("");
                return 0;
            }
            for(int i=1;i<n;++i)
                if (x[i]&1) qwq.push_back(i);
            if (!qwq.empty()){
                printf("%d
    ",(int)qwq.size());
                for(int i:qwq){
                    printf("%d ",i+1);
                }
                puts("");
                return 0;
            }
            for(int i=1;i<n;++i){
                x[i]>>=1;
                y[i]>>=1;
            }
        }
        return 0;
    }
    


    G. Subset with Zero Sum (CF 1270 G)

    题目大意

    给定一个长度为(n)的数组(a),其中第(i)个元素(a_i)满足:(i-nleq a_ileq i-1),请选择一些数使得它们和为(0),并输出它们的位置。保证有解,若有多解,输出任意一种即可。

    解题思路

    这题思路清奇......
    我们将(i-nleq a_ileq i-1)变形得到(1leq i-a_ileq n)
    注意到(i-a_i)仍在([1,n])的范围,我们构造一张有向图,第(i)个点连向第(i-a_i)个点。由于每个点都有条出边,那么一定会有一个环,我们考虑环上的点(i_1,i_2,i_3,...,i_k),分别有:

    • (i_1-a_{i_1}=i_2)
    • (i_2-a_{i_2}=i_3)
    • (i_3-a_{i_3}=i_4)
    • (i_4-a_{i_4}=i_5)
    • ......
    • (i_k-a_{i_k}=i_1)

    累加得(a_{i_1}+a_{i_2}+a_{i_3}+......+a_{i_k}=0)这样我们就找到了一组符合题目要求的(i_1,i_2,i_3,...,i_k)
    (这脑洞是有多大……)

    神奇的代码
    #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); cin.tie(0); cout.tie(0);
        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;
            read(n);
            vector<int> a(n+1);
            for(int i=1;i<=n;++i)
                read(a[i]);
            vector<bool> visit(n+1,false);
            int qwq=1;
            while(!visit[qwq]){
                visit[qwq]=true;
                qwq=qwq-a[qwq];
            }
            vector<int> ans;
            ans.push_back(qwq);
            int qaq=qwq-a[qwq];
            while(qaq!=qwq){
                ans.push_back(qaq);
                qaq=qaq-a[qaq];
            }
            printf("%d
    ",(int)ans.size());
            for(int i:ans) printf("%d ",i);
            puts("");
        }
        return 0;
    }
    


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

  • 相关阅读:
    Python全栈开发之21、django
    Python全栈开发之17、tornado和web基础知识
    Python全栈开发之18、cookies、session和ajax等相关知识
    jquery之别踩白块游戏的实现
    Python全栈开发之16、jquery
    Python全栈开发之15、DOM
    Python全栈开发之13、CSS
    Python全栈开发之12、html
    Go语言学习之路-2-变量与常量
    Go语言学习之路-1-Go语言环境搭建
  • 原文地址:https://www.cnblogs.com/Lanly/p/12121823.html
Copyright © 2011-2022 走看看