Codeforces Round#628(Div.2)解题报告

本文详细解析了Codeforces Round #628(Div.2)的比赛题目,包括A题"EhAb AnD gCd",B题"CopyCopyCopyCopyCopy",C题"Ehab and Path-etic MEXs"和D题"Ehab the Xorcist"。针对每道题目,给出了题目的大致意思、解题思路以及AC代码。
摘要由CSDN通过智能技术生成

题目链接


A题.EhAb AnD gCd

题意
给 一 个 x , 求 a 和 b , 使 得 l c m ( a , b ) + g c d ( a , b ) = x 给一个x,求a和b,使得lcm(a,b)+gcd(a,b)=x xab使lcm(a,b)+gcd(a,b)=x
题解
直 接 令 a = 1 , b = x − 1 直接令a=1,b=x-1 a=1,b=x1

这 样 l c m ( a , b ) = x − 1 , g c d ( a , b ) = 1 , 公 式 成 立 这样lcm(a,b)=x-1,gcd(a,b)=1,公式成立 lcm(a,b)=x1,gcd(a,b)=1

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;



int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;cin>>t;
    while(t--){
        int x;cin>>x;
        cout<<1<<' '<<x-1<<endl;
    }


    return 0;
}


B题.CopyCopyCopyCopyCopy

题意
给 一 个 长 度 为 n 的 数 组 给一个长度为n的数组 n

可 以 把 给 定 的 数 组 再 次 接 到 数 组 后 面 使 数 组 长 度 加 n 可以把给定的数组再次接到数组后面使数组长度加n 使n

这 个 操 作 可 以 执 行 无 数 次 , 问 能 形 成 的 最 长 上 升 序 列 这个操作可以执行无数次,问能形成的最长上升序列
题解
由 于 操 作 可 以 执 行 无 数 次 , 所 以 可 以 把 每 一 个 数 都 取 到 由于操作可以执行无数次,所以可以把每一个数都取到

但 是 题 目 要 求 是 最 长 上 升 序 列 , 中 间 不 能 相 等 , 所 以 重 复 元 素 不 计 但是题目要求是最长上升序列,中间不能相等,所以重复元素不计

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        map<int,int> m;
        int ans=0;
        for(int i=1;i<=n;i++){
            int x;cin>>x;
            if(!m[x])ans++,m[x]++;
        }
        cout<<ans<<endl;
    }


    return 0;
}


C题.Ehab and Path-etic MEXs

题意
n 个 点 形 成 的 连 通 图 , 给 定 n − 1 条 边 n个点形成的连通图,给定n-1条边 nn1

让 你 为 每 条 边 给 定 一 个 l a b e l ( 0 < = x < = n − 2 ) 让你为每条边给定一个label(0 <=x<=n-2) label0<=x<=n2

M e x ( u , v ) 表 示 u 结 点 到 v 结 点 的 简 单 路 中 没 出 现 过 的 l a b e l 的 最 小 值 Mex(u,v)表示u结点到v结点的简单路中没出现过的label的最小值 Mex(u,v)uvlabel

让 你 给 定 一 种 方 式 , 令 ∀ u ∀ v M a x ( u , v ) 的 值 最 小 让你给定一种方式,令∀u∀vMax(u,v)的值最小 uvMax(u,v)
题解
将 分 叉 的 位 置 ( 即 度 大 于 2 的 点 ) 周 围 的 任 意 三 条 边 给 上 0 , 1 , 2 的 l a b e l 将分叉的位置(即度大于2的点)周围的任意三条边给上0,1,2的label (2)012label

其 他 点 可 以 随 意 给 其他点可以随意给

这 样 给 后 , 任 意 一 条 简 单 路 会 不 通 过 该 点 的 分 叉 , 或 者 通 过 其 中 一 条 或 两 条 这样给后,任意一条简单路会不通过该点的分叉,或者通过其中一条或两条

这 样 的 话 , 除 了 成 链 不 管 怎 样 M e x ( u , v ) 都 不 会 超 过 2 这样的话,除了成链不管怎样Mex(u,v)都不会超过2 Mexuv2

如 果 形 成 了 一 条 链 , 那 么 在 树 的 直 径 里 一 定 所 有 数 会 全 部 包 括 , 所 以 不 管 怎 么 给 结 果 都 是 一 定 的 如果形成了一条链,那么在树的直径里一定所有数会全部包括,所以不管怎么给结果都是一定的
AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;

int n;
int de[maxn],ans[maxn];
vector<pii> g[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>n;
    memset(ans,-1,sizeof ans);
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        de[u]++,de[v]++;
        g[u].pb(mp(v,i));
        g[v].pb(mp(u,i));
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(de[i]>2){
            for(auto j:g[i]){
                ans[j.se]=cnt++;
                if(cnt==3)break;
            }
            break;
        }
    }
    for(int i=1;i<n;i++)
        if(ans[i]==-1)ans[i]=cnt++;
    for(int i=1;i<n;i++)
        cout<<ans[i]<<endl;
    return 0;
}


D题.Ehab the Xorcist

题意
给 定 一 个 u 代 表 一 个 数 组 的 全 部 异 或 给定一个u代表一个数组的全部异或 u

给 定 一 个 v 代 表 一 个 数 组 的 全 部 和 给定一个v代表一个数组的全部和 v

问 你 这 个 数 组 最 短 的 长 度 及 其 每 个 元 素 问你这个数组最短的长度及其每个元素
题解
对于二进制 a + b a+b a+b的某一位来说
a   x o r   b a ~xor~b a xor b可以表示 a + b a+b a+b的本位, a a a& b b b可以表示 a + b a+b a+b的进位
然后将 a a a& b b b左移一位就可以表示 a + b a+b a+b
所以可以得到
a + b = a   x o r   b + 2 ∗ a & b a+b=a~xor~b+2*a\&b a+b=a xor b+2a&b

所以通过本题可以推出
v = u + 2 ∗ a & b v=u+2*a\&b v=u+2a&b

所以可以知道如果 u > v u>v u>v或者 ( u − v ) % 2 = 1 (u-v)\%2=1 (uv)%2=1这样是恒不成立的
然后特判一下 u = v u=v u=v的情况
i f ( u = v = 0 ) 数 组 是 空 的 if (u=v=0)数组是空的 if(u=v=0)

e l s e 数 组 里 只 有 一 个 元 素 u else 数组里只有一个元素u elseu

其他情况下数组肯定至少有两个元素
然后通过刚才的公式计算出 a & b a\&b a&b,循环判断 a & b a\&b a&b a   x o r   b a~xor~b a xor b的每一个二进制位
如果 a & b a\&b a&b在该位是 1 1 1,说明该位每个数都为 1 1 1,所以用 c n t [ i ] + = 2 cnt[i]+=2 cnt[i]+=2
如果 a   x o r   b a~xor~b a xor b在该位是 1 1 1,说明该位有奇数个 1 1 1,所以需要 c n t [ i ] + = 1 cnt[i]+=1 cnt[i]+=1
这样 c n t cnt cnt数组的最大数就代表数组的长度
最后循环每次取出一个作为其中一个数二进制位的第i位
首先令 x = a & b = ( v − u ) / 2 x=a\&b=(v-u)/2 x=a&b=(vu)/2
如果长度为 3 3 3的情况就是出现过两个都为 1 1 1的时候 ( ( ( 即 u & x ! = 0 即u\&x!=0 u&x!=0 ) ) )
长度为 3 3 3的时候,其实每个二进制位 x = 1 x=1 x=1的时候都在这位加了两次,所以数组中会出现两个 x x x,由于每次在某二进制位 u = 1 u=1 u=1的时候该位都会加 1 1 1,所以数组中可以分离出一个 u u u
最终可以确定此时数组的元素为 [ u , x , x ] [u,x,x] [u,x,x]

如果长度为 2 2 2的情况就是没出现过两个都为 1 1 1的时候 ( ( ( 即 u & x = = 0 即u\&x==0 u&x==0 ) ) )
此时可以发现数组依旧可以分离出两个 x x x,一个 u u u,但是此时的数组长度为2,不能全部直接放到数组里。但是此时 u & x = = 0 u\&x==0 u&x==0,说明如果 u + x   x u+x~x u+x x为1的二进制位u都为0,所以再用一个 x x x二者异或就会重新得到u
所以可以得到最后数组的元素为 [ u + x , x ] [u+x,x] [u+x,x]

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ll u,v;cin>>u>>v;
    if(v-u<0||(v-u)%2){cout<<-1;return 0;}
    ll d=v-u;
    if(!d){
        if(!u)cout<<0;
        else cout<<1<<endl<<u;
    }
    else{
        ll t=d/2;
        if((t&u)==0)cout<<2<<endl<<t<<' '<<u+t<<endl;
        else cout<<3<<endl<<t<<' '<<t<<' '<<u<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值