Codeforces Round #499 (Div. 1)部分题解(B,C,D)

Codeforces Round #499 (Div. 1)


这场本来想和同学一起打\(\rm virtual\ contest\)的,结果有事耽搁了,之后又陆陆续续写了些,就综合起来发一篇题解。


B.Rocket

极其简单的一道交互题,有些位置会说反的,那么就选一个数来询问直接选出所有的这样的位置

显然,选择\(\rm 1\)\(\rm m\)都可以,选择完之后直接二分就行了

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=41;
int n,m,now,flag;bool vis[maxn];
int check(int x,int now){
    int g;
    printf("%d\n",x),fflush(stdout),read(g);
    if(vis[now])g=-g;return g;
}
int main(){
    read(m),read(n);
    for(rg int i=1;i<=n;i++){
        printf("%d\n",m),fflush(stdout);read(now);
        if(now==0)return 0;
        else if(now==-1)vis[i]=1;
    }
    int l=1,r=m;now=1;
    while(l<=r){
        int mid=(l+r)>>1,f=check(mid,now);
        if(!f)return 0;
        if(f==-1)l=mid+1;else r=mid-1;
        now++;if(now==n+1)now=1;
    }
}

C.Border

这题其实也挺显然的,首先我们肯定只用管每个数\(\rm k\)进制下的最后一位的值,思考一下组合的过程,发现对于\(\rm x,y\),似乎\(\rm gcd(k,x,y)\)的倍数都能够被组合出来,然后大胆猜测这是对的,那么所有数和\(\rm k\)的最大公约数的答案就是能够组成的数

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e5+10;
int n,m,a[maxn],now;
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int main(){
    read(n),read(m),now=m;
    for(rg int i=1;i<=n;i++)read(a[i]),a[i]=a[i]%m,now=gcd(now,a[i]);
    if(!now)return printf("%d\n%d\n",1,0),0;
    printf("%d\n",m/now);
    for(rg int i=0;i<m/now;i++)printf("%d ",i*now);
}

D.Mars rover

确实也不难,差不多是一眼秒的题

由于每次都只修改一个点,然后我们发现对于这次修改,只要它到根的路径上只要有一个点不受这次变化的影响,那么根节点就不会受到影响。

那么我们可以发现这个过程可以从上往下做,对于每一个有两个儿子的点,如果它的左儿子取反后它的值不受影响,那么根节点也不会受到影响,也就是说它的左儿子这个子树内的所有叶子节点的取反对根节点都没有影响,右儿子亦然

这样我们就可以\(O(n)\)扫一遍先算出初始树上的节点权值,然后在\(O(n)\)扫一遍得出每个叶子节点对根节点是否有影响就行了

总时间复杂度\(O(n)\)

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e6+10;
int n,m,f[maxn],ans,a[maxn],l[maxn][3];
char s[maxn][5];
bool vis[maxn];
void dfs(int x){
    if(l[x][0]==1){
        dfs(l[x][1]);
        f[x]=!f[l[x][1]];
    }
    else if(l[x][0]==2){
        dfs(l[x][1]),dfs(l[x][2]);
        if(s[x][1]=='A')f[x]=f[l[x][1]]&f[l[x][2]];
        if(s[x][1]=='O')f[x]=f[l[x][1]]|f[l[x][2]];
        if(s[x][1]=='X')f[x]=f[l[x][1]]^f[l[x][2]];
    }
}
void solve(int x,int now){
    vis[x]=now;
    if(l[x][0]==1)solve(l[x][1],now);
    else if(l[x][0]==2){
        if(s[x][1]=='A'){
            int now1=(!f[l[x][1]])&f[l[x][2]],now2=(!f[l[x][2]])&f[l[x][1]];
            if(now1!=f[x])solve(l[x][1],now);
            else solve(l[x][1],0);
            if(now2!=f[x])solve(l[x][2],now);
            else solve(l[x][2],0);
        }
        if(s[x][1]=='O'){
            int now1=(!f[l[x][1]])|f[l[x][2]],now2=(!f[l[x][2]])|f[l[x][1]];
            if(now1!=f[x])solve(l[x][1],now);
            else solve(l[x][1],0);
            if(now2!=f[x])solve(l[x][2],now);
            else solve(l[x][2],0);
        }
        if(s[x][1]=='X'){
            int now1=(!f[l[x][1]])^f[l[x][2]],now2=(!f[l[x][2]])^f[l[x][1]];
            if(now1!=f[x])solve(l[x][1],now);
            else solve(l[x][1],0);
            if(now2!=f[x])solve(l[x][2],now);
            else solve(l[x][2],0);
        }
    }
}
int main(){
    read(n);
    for(rg int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
        if(s[i][1]=='A'||s[i][1]=='O'||s[i][1]=='X')
            l[i][0]=2,read(l[i][1]),read(l[i][2]);
        else if(s[i][1]=='N')l[i][0]=1,read(l[i][1]);
        else l[i][0]=0,read(f[i]);
    }
    dfs(1),solve(1,1);
    for(rg int i=1;i<=n;i++)
        if(s[i][1]=='I'){
            if(vis[i])printf("%d",!f[1]);
            else printf("%d",f[1]);
        }
}
posted @ 2019-06-20 15:32 蒟蒻--lichenxi 阅读(...) 评论(...) 编辑 收藏