Codeforces Round #628 解补题报告

A. EhAb AnD gCd
题意:
给定两个数的gcd和lcm的和x,要求输出任意一组这对数。
思路:
考虑1的特殊性,1与任意数的gcd都是1,与任意数的lcm都是该数。
所以答案就是1和x-1了
最开始想偏了,还证明了几分钟别的……
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}
int main(){
    int t;cin>>t;
    while(t--){
        ll n;cin>>n;
        printf("1 %lld\n",n-1);
    }
    return 0;
}

B. CopyCopyCopyCopyCopy
题意:
给你一个长度为n的数组,问将该数组复制n次后得到的最长上升子序列的长度是多少。
思路:
我们记数组中不同元素的个数为sum,因为可以将该数组复制n次,我们可以在第一个数组中取出第一小的元素,在第二个数组中取出第二小的元素,以此类推,长度最大是sum
代码:
map写法 也可以直接用set计算,写map写习惯了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
ll a[maxn];
map<ll,ll>mp;
int main(){
    ll t;cin>>t;
    while(t--){
        ll n;mp.clear();
        cin>>n;
        ll res=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(mp[a[i]]==0) mp[a[i]]=1,res++;
            //else res++;
        } 
        cout<<res<<endl;
    }
    return 0;
}

C. Ehab and Path-etic MEXs
题意:
给你一棵树,边的权值为0~n-2,问如何分配权值才能使得题意中的MEX最大值尽可能的小
思路:
先来考虑特殊情况,如果所有点的度都小于等于2,说明这棵树就是一条链,这时候怎么赋值都无所谓。
当有个点的度数大于2时,我们把0,1,2分别赋给他的三个边,其余的赋值不重的边就可以了。这时候,所有的路径都不会同时经过权值为0,1,2的边,得到的MEX最大值一定是最小的,此时MEX为2。
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
int u[maxn],v[maxn];
int s[maxn];
int main(){
    int n;cin>>n;
    for(int i=1;i<n;i++){
        cin>>u[i]>>v[i];
        s[u[i]]++;s[v[i]]++;
    }
    int root=-1;
    for(int i=1;i<=n;i++){
        if(s[i]>=3){//找度数大于2的点
            root=i;
            break;
        }
    }
    if(root==-1)//一条链
        for(int i=1;i<n;i++) cout<<i-1<<endl;
    else{
        int x=3,cnt=0;
        for(int i=1;i<n;i++){
            if((v[i]==root||u[i]==root)&&cnt<3) cout<<cnt++<<endl;
            else cout<<x++<<endl;
        }
    }
    
    return 0;
}

D - Ehab the Xorcist
题意:
给你u,v,要求构造一个最短的数组,使得其所有元素异或为u,和为v
思路:
我们可以把异或看成是不进位的加法,这样就可以推出以下几种特殊情况(当时是真没往这想)
(1)当u>v时,一定无解。因为不存在一些数使得不进位的加法的和比进位的加法的和大
(2)当u == v == 0时,答案是0
(3)当u==v!=0时,答案是u,长度为1
再来看普通情况
根据异或的性质x^x=0,所以我们可以知道【u,x,x】满足要求,这时x=(v-u)>>1;这也就要求v-u一定要是偶数,所以当v-u是奇数时也就不能构造了。
然后就是神仙思路了

如果u和x的二进制上,没有一位两个都是1的,那么这时候u^x=u+x
所以可以把u和x合并为u+x,这样就变成了最短长度~

其余几个注意点都在代码里了~
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//注意数据范围~
const int maxn=1e6+7;
int main(){
    ll u,v;
    cin>>u>>v;
    if(u>v||(v-u)%2) puts("-1");
    else if(u==v){
        if(u==0) puts("0");
        else cout<<"1"<<endl<<u<<endl;
    }
    else{
        ll x=(v-u)>>1;
        //注意优先级
        if((x^u)==x+u) cout<<"2"<<endl<<x+u<<" "<<x<<endl;
        else cout<<"3"<<endl<<u<<" "<<x<<" "<<x<<endl;
    }
    return 0;
}

参考博客:传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙睡不醒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值