Codeforces Round #628 (Div. 2) Mar/14/202022:35UTC+8

比赛链接 https://codeforces.com/contest/1325
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197

C. Ehab and Path-etic MEXs

在这里插入图片描述

思路:防止 0、1、2放在同一条链上
考虑: m e x ≥ 1 mex\ge 1 mex1 m e x ≥ 2 mex\ge 2 mex2 m e x ≥ 3 mex\ge 3 mex3的情况

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10,inf=1e9;

int n;
vector<pair<int,int> > G[maxn];
int label[maxn];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n-1;++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back({v,i});
        G[v].push_back({u,i});
    }
    memset(label,-1,sizeof(label));
    for(int i=1;i<=n;++i)
    {
        if(G[i].size()>=3)
        {
            for(int j=0;j<=2;++j)
                label[G[i][j].second]=j;
            int cnt=2;
            for(int j=1;j<=n-1;++j)
                if(label[j]==-1)
                    label[j]=++cnt;
            for(int j=1;j<=n-1;++j)
                cout<<label[j]<<"\n";
            return 0;

        }
    }

    for(int i=1;i<=n-1;++i)
        cout<<i-1<<"\n";
    return 0;
}

D. Ehab the Xorcist

在这里插入图片描述
题意:构造一个数组,使得和为v,异或和为 u
思路

  • u、v的奇偶性相同:因为 a + b = a a+b=a a+b=a ^ b + 2 ( a & b ) b+2(a\&b) b+2(a&b),奇偶性不变
  • u大于v时无解,异或是不进位加法,不可以大于加法
  • u==v时,答案为 u
  • 最长长度为 3 : 因为存在 u 、 v − u 2 \frac{v-u}2 2vu v − u 2 \frac{v-u}2 2vu
  • 考虑长度为2的情况,即构造 a 和 b。由于 a + b = a a+b=a a+b=a ^ b + 2 ( a & b ) b+2(a\&b) b+2(a&b),得到 ( a & b ) = v − u 2 (a\&b)=\frac{v-u}2 (a&b)=2vu
    &运算相当于取公共位,而 ^ 相当于不要公共位。
  • 那么就取 ( a & b ) = v − u 2 = b (a\&b)=\frac{v-u}2=b (a&b)=2vu=b,即 b b b 取公共位,取: a = u − b a=u-b a=ub,判断一下, a a a ^ b = = u b==u b==u即可
  • 因为在 a 里面包含了 非公共位和公共位,这些位可能会产生进位,所以需要判断
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10,inf=1e9;


int main()
{
    ll u,v;
    cin>>u>>v;
    if(u>v||(u-v&1))
    {
        puts("-1");
        return 0;
    }
    if(u==v&&v==0)
    {
        printf("%lld\n",u);
        return 0;
    }


    if(u==v)
    {
        puts("1");
        printf("%lld\n",u);
        return 0;
    }

    ll a=(v-u)/2;
    ll b=v-a;
    if((a^b)==u)
    {
        puts("2");
        printf("%lld %lld\n",a,b);
    }
    else
    {
        puts("3");
        printf("%lld %lld %lld\n",u,a,a);
    }
    return 0;
}

E. Ehab’s REAL Number Theory Problem

在这里插入图片描述
题意:在数组a ,找最小的子序列,使得子序列每一项的乘积为平方数。输出最小的长度,每个元素的素因子不超过7个
思路:每一个元素最多两个素因子。这样,就只剩下 1、p、pq 这样的数,每个素因子看成一个点,对它们进行连边。最后如果找到一个环,就一定是一个平方数,找一个最小的环。因为数据为1e6,所以可以在[1,1000]内枚举起点

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+10,inf=0x7f7f7f7f;

int n,a[maxn];
const int N=10000;
int pcnt,prime[N+10],visit[N+10];
void init()
{
    pcnt=0;
    for(int i=2;i<=N;++i)
    {
        if(!visit[i]) prime[++pcnt]=i;
        for(int j=1;j<=pcnt&&i*prime[j]<=N;++j)
        {
            visit[i*prime[j]]=1;
            if(i%prime[j]==0)
                break;
        }
    }
}

int head[maxn],cnt;
struct Edge
{
    int to,nxt;
}edges[maxn<<1];

void add(int u,int v)
{
    edges[++cnt].to=v;
    edges[cnt].nxt=head[u];
    head[u]=cnt;
}

void solve(int n)
{
    if(n==1)
    {
        add(1,1),add(1,1);
        return;
    }

    vector<int> p;
    for(int i=1;prime[i]*prime[i]<=n;++i)
    {
        if(n%prime[i]==0)
        {
            int res=0;
            while(n%prime[i]==0)
                n/=prime[i],res++;
            if(res&1)
                p.push_back(prime[i]);
            else
            	p.push_back(1);
        }
    }
    if(n>1)
        p.push_back(n);

    if(p.size()==1)
        add(1,p[0]),add(p[0],1);
    else if(p.size()==2)
        add(p[0],p[1]),add(p[1],p[0]);
}

int depth[maxn],fa[maxn];
int ans=inf;

int bfs(int s)
{
    memset(depth,inf,sizeof(depth));
    memset(fa,-1,sizeof(fa));
    queue<int> q;
    q.push(s);
    depth[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edges[i].nxt)
        {
            int v=edges[i].to;
            if(v==fa[u])
                continue;
            if(depth[v]==inf)
            {
                depth[v]=depth[u]+1;
                q.push(v);
                fa[v]=u;
            }
            else
                ans=min(ans,depth[v]+depth[u]+1);
        }
    }
    return inf;
}

int main()
{
    init();
    memset(head,-1,sizeof(head)),cnt=-1;
    cin>>n;
    for(int i=1;i<=n;++i)
        cin>>a[i],solve(a[i]);
    for(int i=1;i<=1000;++i)
        if(!visit[i])
            bfs(i);

    if(ans==inf) puts("-1");
    else printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值