zoukankan      html  css  js  c++  java
  • 【Codeforces Round #435 (Div. 2) A B C D】

    CF比赛题目地址:http://codeforces.com/contest/862

    A. Mahmoud and Ehab and the MEX

    ·英文题,述大意:
          输入n,x(n,x<=100),然后输入n个数作为一个集合。现在可以进行多次操作,每次操作为删除一个数或者添加一个数,求最少操作数使得集合Mex值等于x。

    ·分析:

         也许是考察Mex的吧~那就当复习了,我们的策略是,如果当前集合的  Mex比x小,那就一直添加数;如果Mex比x大,那么就删除那个和x相同的元素就可以了。最后Mex==x输出0即可。

    ·代码:

    1 #include"stdio.h"
    2 #define go(i,a,b) for(int i=a;i<=b;i++)
    3 int n,x,a,ans;bool exist[105];
    4 int main()
    5 {
    6     scanf("%d%d",&n,&x);
    7     go(i,1,n)scanf("%d",&a),exist[a]=1;
    8     go(i,0,x-1)ans+=exist[i]^1;if(exist[x])ans++;printf("%d
    ",ans);return 0;
    9 }//Paul_Guderian

    B. Mahmoud and Ehab and the bipartiteness

    ·英文题,述大意:
          输入一个二分图,保证它是一个树(二分树……)。现在要使得原树变成完全二分图,求最多加入边数。完全二分图长这个样子:

                               image

    ·分析:

         如上图,我们可以知道最后的总边数为:4*3(即两边点数相乘)。由于树的边数等于节点数减一,所以呢答案就是a*b-树边数(a,b分别为二分图两边的点数)。所以这道题清晰地告诉我们,它只需要一个二分图染色统计二分图两边的个数就可以了。

    ·呆呆的代码:

     1 #include<stdio.h>
     2 #define go(i,a,b) for(int i=a;i<=b;i++)
     3 #define fo(i,a,x) for(int i=a[x],v=e[i].v;i;i=e[i].next,v=e[i].v)
     4 const int N=100003;
     5 struct E{int v,next;}e[N*2];int n,head[N],k=1,c[N],w;
     6 void ADD(int u,int v){e[k]=(E){v,head[u]};head[u]=k++;}
     7 void Dye(int u,int fa){fo(i,head,u)if(v!=fa)w+=(c[v]=3-c[u])==2,Dye(v,u);}
     8 int main()
     9 {
    10     scanf("%d",&n);go(i,2,n){int u,v;scanf("%d%d",&u,&v);ADD(u,v);ADD(v,u);}
    11     c[1]=1;Dye(1,1);printf("%I64d
    ",1ll*w*(n-w)-n+1);return 0;
    12 }//Paul_Guderian

    C. Mahmoud and Ehab and the xor

    ·英文题,述大意:

          输入n,x(0<n<=105,0<=x<=105),表示现在需要我们构造一个含有n个不同元素的集合,并且满足:①元素为不大于106的非负整数②所有元素的异或结果等于x。如果可以构造,输出YES并且输出这个集合中的所有元素(按照任何顺序);如果不能,那么输出NO即可。

    ·分析:

          看见这道题可能会纠结于怎样判断输出no还是yes的情况。但是事实上,根据异或的美妙(后文就会体现),仅有一种情况会输出no—n=2,x=0。

    所以其他的都是Yes,那么怎么找出集合的n个元素呢?

          我们知道异或的一个巧妙性质:0^任何数=0,偶数个相同的数抑或的结果为0。既然挨着挨着找每个元素很麻烦,那我们尝试使用这个性质,使得我们可以先胡乱取数异或出一个结果,然后再试图调整这个混乱的结果使它和x相等。

          为什么会这样想?因为题目中有关键信息:元素大小不超过106,但是x是不超过105,意思说有一段区间x不存在。那么结合上文的胡乱思想,我们可以这样:现在已经将一些数异或起来了,答案是y。我们分情况讨论:

         (1)x!=y:我们的目的是将y变回x,根据上文发现的异或性质,我们可以给y先抑或上一个y,再异或上一个x,就成为答案了!但是伤心的是,y万一已经用过了呢?这很难保证有没有用过。所以我们想到了可以找一个较大的数字,即在105~106的数字,因为它的二进制最高位是不会被改变的,由于选择的元素小于105所以在(105,106)之内选出的数是不会重复的,我们设这个很大的数字为a,那么我们将y依次异或上a和(a^x^y)这两个数,那不就既保证元素不重复,又保证异或结果为x了吗?OK。

         (2)x==y:继续用上文的a和(a^x^y)不行了,因为x==y,那么这两个元素也是相同的。我们将其改成:a,a*2和(a^(a*2))这三个数,那么也可以满足条件。

          最终的方法是:先将1~n-3的数异或起来的到y,然后:

            如果x!=y:剩下三个元素为{0,a,a^x^y}

           如果x==y:剩下三个元素为{a,a*2,a^(a*2)}

    Over,呆码如下:

     1 #include"stdio.h"
     2 #define R return 0
     3 #define go(i,a,b) for(int i=a;i<=b;i++)
     4 int n,x,a=(1<<17),b=(1<<18),y;
     5 int main()
     6 {
     7     scanf("%d%d",&n,&x);//QAQ 
     8     if(n==2&&!x){puts("NO");R;}puts("Yes");
     9     if(n==1){printf("%d
    ",x);R;}
    10     if(n==2){printf("%d %d
    ",0,x);R;}
    11     go(i,1,n-3)y^=i,printf("%d ",i);x!=y?
    12     printf("%d %d %d
    ",0,a,a^x^y):
    13     printf("%d %d %d
    ",a,b,a^b);return 0;
    14 }//Paul_Guderian

    D. Mahmoud and Ehab and the binary string

    ·[题外话:那天晚上和圆盘盘全卡在C题,然后我果断去了D题,AC掉了从而保住了Rating]

    ·英文题,述大意:
          这是一道交互题。输入n(n<=1000),表示这里有一个隐秘的长度为n的01串。现在你可以询问系统最多15次,询问内容为:输出一个长度为n的01串,然后系统会告诉你那个隐秘的串和你的这个串的汉明距离。最终你需要输出的答案,答案内容是输出任意一个0和1的下标(即输出两个下标,比如0100,你就输出1 2……)。

    ·分析:
          这样瞅瞅:n->1000,q->15有啥联系?至少我第一反应是:210=1024。因此我立下了用二分解决这道题的决心。初始情况下总要有一个串吧,所以可以初始化一个全为1的串。然后这样的结论可以高效解决问题:

                 image

    ·设右边半段长度为m,则有:
    ·如果X=Y+m,那么隐秘01串的右半段全是0;
    ·如果Y=X+m,那么隐秘01串的右半段全是1;
    ·若两种情况都不满足,那么:右半段必定同时含有01,我们就继续二分;

    ·因为答案在这里面都找得到,最终统计好了输出就是啦。

    代码在这里:

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #define _ fflush(stdout)
     4 #define go(i,a,b) for(int i=a;i<=b;i++)
     5 int n,T=15,d,dis,_0,_1;char s[1003],t[1003]; 
     6 void dfs(int l,int r)
     7 {
     8     if(l==r)
     9     {
    10         go(i,1,n)t[i]=s[i];t[l]='0';
    11         putchar('?');putchar(' ');puts(t+1);_;
    12         scanf("%d",&d);if(dis<d)_1=l;else _0=l;
    13     }
    14     
    15     if(_0&&_1){printf("! %d %d
    ",_0,_1);_;exit(0);}
    16     
    17     int M=l+r>>1;go(i,1,n)t[i]=s[i];go(i,M+1,r)t[i]='0';
    18     putchar('?');putchar(' ');puts(t+1);_;scanf("%d",&d);
    19     
    20     if(d==dis-(r-M)){_0=r;dfs(l,M);return;}
    21     if(d==dis+(r-M)){_1=r;dfs(l,M);return;}dfs(M+1,r);
    22 }
    23 int main()
    24 {
    25     scanf("%d",&n);go(i,1,n)s[i]='1';
    26     putchar('?');putchar(' ');puts(s+1);_;
    27     scanf("%d",&dis);dfs(1,n);return 0;
    28 }//Paul_Guderian

     

     

     

    我闻到初春的味道,那如同儿时梦境新鲜的芬芳;

    也尝到思念的苦涩,这回望远方秋雨般无垠的萧索…——汪峰《无处安放》

  • 相关阅读:
    supervisor 配置
    单链表
    二叉排序树
    python 排序
    64 位 Ubuntu 下 android adb 不可用解决方法
    python 获取文件夹大小
    Ubuntu mongodb 安装和配置
    关于c3p0配置详细说明
    dwr消息推送
    关于如果修改 ie 浏览器 文本模式
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/7561897.html
Copyright © 2011-2022 走看看