Codeforces Round #379 (Div. 2)题解

A.Anton and Danik(734A)

统计字符串中两种字符的数量即可

B.Anton and Digits(734B)

题意:数字2,3,5,6的个数分别为k2,k3,k5,k6,用这些数字组成32和256,问组成的数字的和的最大值为多少。
题解:贪心。先找出所有的256,再找出32。

C.Anton and Digits(734C)

题意:要生产n瓶药水,每生产一瓶药水花费时间x,有两种操作,数量分别为m和k。
操作一:花费bi点魔法值,使每生产一瓶药水的时间变为ai。
操作二:花费ci点魔法值,立刻生产出ci瓶药水。
每种操作最多进行一次,有s点魔法值。
问生产出n瓶药水的最短时间。
题解:因为bi和ci都是非递减的,所有枚举第一种操作,二分第二种操作,记录最小值即可。

D.Anton and Chess(734D)

题意:在有一个无限大的棋盘上有一个国王,和n个棋子,棋子的类型为车,象或王后,问是否有棋子可以攻击到国王。
题解:向国王的8个方向扫描,找到每个方向上离国王最近的棋子,然后判断该方向上棋子是否可以攻击到国王。

E.Anton and Tree(734E)

题意:给你一颗树,树上的点只有两种颜色,每次操作可以把一个颜色全部相等的点连通块变成另一种颜色,问最少进行多少次操作可以把书上的点边成一种颜色。
题解:先把颜色相同的连通块缩成一个点,然后缩完点后的树的直径,直径的一半即为答案。
代码

#include <bits/stdc++.h>
using namespace std;
#define N 200010
vector<int> g[N];
int head[N],pre[N*2],to[N*2],c[N],belong[N],a[N*2],b[N*2],h[N];
bool vis[N];
int n,e=1,tot=0,z=0;
void addedge(int x,int y)
{
    to[e]=y;pre[e]=head[x];head[x]=e++;
}
void dfs(int x)
{
    belong[x]=tot;
    vis[x]=true;
    int y;
    for(int i=head[x];i;i=pre[i])
    {
        y=to[i];
        if(!vis[y]&&c[y]==c[x]) dfs(y);
        if(c[y]!=c[x])
        {
            a[++z]=x;b[z]=y;
        }
    }
}
void dfs1(int x,int p)
{
    for(int i=0;i<g[x].size();++i)
    {
        if(g[x][i]==p) continue;
        h[g[x][i]]=h[x]+1;
        dfs1(g[x][i],x);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&c[i]);
    int x,y,maxx;
    for(int i=1;i<n;++i)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    for(int i=1;i<=n;++i)
        if(!vis[i])
        {
            ++tot;
            dfs(i);
        }
    for(int i=1;i<=z;++i)
        if(belong[a[i]]!=belong[b[i]])
            g[belong[a[i]]].push_back(belong[b[i]]);
    dfs1(1,0);
    maxx=0;
    for(int i=1;i<=tot;++i)
        if(maxx<h[i])
        {
            maxx=h[i];x=i;
        }
    h[x]=0;
    dfs1(x,0);
    maxx=0;
    for(int i=1;i<=tot;++i)
        if(maxx<h[i]) maxx=h[i];
    printf("%d\n",maxx+1>>1);
    return 0;
}

F.Anton and School(734F)

题意:已知

{bi=(ai and a1)+(ai and a2)++(ai and an),ci=(ai or a1)+(ai or a2)++(ai or an),

给出bi和ci,求出ai
题解:因为
(x and y)+(x or y)=x+y,

所以
bi+ci=nai+a1+a2++an,

所以
i=1n(bi+ci)=2n(a1+a2++an),

所以
sum=i=1nai=ni=1(bi+ci)2n,

所以
ai=bi+cisumn,

求出ai后,再根据求出的ai求出b1i和c1i,判断b1i和bi,c1i和ci是否相同即可。
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 200010
ll b[N],c[N],b1[N],c1[N],a[N],bits[30];
ll n;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n;
    for(int i=1;i<=n;++i) cin>>b[i];
    for(int i=1;i<=n;++i) cin>>c[i];
    ll sum=0;
    for(int i=1;i<=n;++i) sum+=b[i]+c[i];
    sum/=2*n;
    for(int i=1;i<=n;++i)
    {
        a[i]=(b[i]+c[i]-sum)/n;
        if(a[i]<0)
        {
            cout<<-1;
            return 0;
        }
    }
    for(int i=1;i<=n;++i)
        for(int j=0;j<30;++j)
            if(a[i]&(1<<j))
                ++bits[j];
    for(int i=1;i<=n;++i)
    {
        for(int j=0;j<30;++j)
        {
            if(a[i]&(1<<j))
            {
                b1[i]+=(1LL<<j)*bits[j];
                c1[i]+=(1LL<<j)*n;
            }
            else c1[i]+=(1LL<<j)*bits[j];
        }
        if(b1[i]!=b[i]||c1[i]!=c[i])
        {
            cout<<-1;
            return 0;
        }
    }
    for(int i=1;i<=n;++i)
        cout<<a[i]<<' ';
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值