Codeforces Round 628部分题解

A.EhAb AnD gCd
原题链接:
https://codeforces.com/contest/1325/problem/A
题意:
给出一个x,求得两个数a,b,使得gcd(a,b)+lcm(a,b)==x;
gcd:最大公约数,lcm最大公倍数
题解:
1和任何正整数得gcd是1,lcm是该正整数。
所以直接输出1和x-1即可。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		LL x;
		cin>>x;
		cout<<1<<" "<<x-1<<"\n";
	}
	return 0;
}

B.CopyCopyCopyCopyCopy
原题链接:
https://codeforces.com/contest/1325/problem/B
题意:
给定一个数组,这个数组可以被连续复制无限次,这里的复制是指将一个原数组的copy添加至原数组的末尾。问最长上升子序列的长度。
题解:
因为可以复制无穷次,所以在每一个复制的数组中,选取当前最小的元素来构成最长上升子序列即可。所以只需要知道原数组有多少个不重复元素即可。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
#define LL long long

set<int > s;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			int x;
			cin>>x;
			s.insert(x);
		}
		cout<<s.size()<<"\n";
		s.clear();
	}
	return 0;
}

C.Ehab and Path-etic MEXs
原题链接:
https://codeforces.com/contest/1325/problem/C
题意:
通过输入构造一棵n个节点的树,现在要求给每条边编号从0-n-2,且每条边的编号各不相同。定义MEX(u,v)为u节点到v节点的最短路径中所经历边中未出现的最小的自然数。问如何编号,使得对于所有的MEX(u,v)中的最大值最小。
题解:
构造题,对于一个度大于等于三的节点,将与该节点连接的三个边编号0,1,2,其余所有边随意赋值3至n-2即可。
如果没有一个度大于等于三的节点,可以想的出这是一条单链,直接随机从0至n-3即可。
原因:
在所有的最短路径中一定会包含经过0边和1边的最短路径(起始边结束边)。所以max({MEX(u,v)})无论怎么构造一定大于等于2.
没有任何一个最短路径会同时经过一个节点的三条边。所以保证了所有的MEX(u,v)最大值为2.
对于单链来说,无论怎么编号,一定有一个最短路径是从单链一侧到另一侧即包含所有的边,所以无论怎么编号,max({MEX(u,v)})都是n-1。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
#define LL long long
const int maxn=1e6+5;
int n;
vector<pair<int,int> > edge[maxn];
int ans[maxn];//记录每条边的编号
bool vis[maxn];//标记每条边是否被编号

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        edge[u].push_back(make_pair(v,i));
        edge[v].push_back(make_pair(u,i));
    }
    int a=0;
    for(int i=1;i<=n;i++)
    {
        if(edge[i].size()<=2)continue;
        for(int j=0;j<3;j++)
        {
            ans[edge[i][j].second]=j;
            vis[edge[i][j].second]=1;
        }
        a=3;
        break;
    }
    for(int i=1;i<n;i++)
        if(!vis[i])ans[i]=a++;
    for(int i=1;i<n;i++)
        cout<<ans[i]<<"\n";
    return 0;
}

D.Ehab the Xorcist
原题链接:
https://codeforces.com/contest/1325/problem/D
题意:
给两个长整型u,v,求出一个数组,使得数组所有的元素异或和等于u,和等于v,并且数组长度最小。
题解:
一个数组的异或和一定小于一个数组的和。所以u<=v。
现在来构造数组,因为数组和等于v,所以相当于把v拆分开来。
如果u==v,那么数组元素为u即可。
如果u<v,那么长度为1的数组截然不可能 。
设dt=v-u:

  • 如果dt为偶数,很容易得到u^(dt/2)^(dt/2)=u,u+dt/2+dt/2=v;这么就构造出了长度为三的数组,当u与dt/2的二进制中每一位都不相同的话,可以将一个dt/2加到u上,即(u|(dt/2))。这样就构造出了长度为2的数组{(u|(dt/2)),dt/2}。
  • 如果dt为奇数也就是dt/2无法整除,那么则无法构造出满足题意得数组,输出-1.

AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
#define LL long long
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    LL u,v,k=2;
    cin>>u>>v;
    LL dt=v-u;
    if (u==v && u==0)
    {
        cout<<0;
        return 0;
    }
    if (dt<0 || (dt&1))
    {
        cout<<-1;
        return 0;
    }
    if (dt==0)
    {
        cout<<1<<"\n"<<u;
        return 0;
    }
    dt>>=1;
    for (int i=0; i<=61; i++)
    {
        if ((u&(1ll<<i)) && (dt&(1ll<<i)))
        {
            k=3;
            break;
        }
    }
    if (k==2)
    {
        cout<<2<<"\n"<<(u|dt)<<" "<<dt;
    }
    else
    {
        cout<<3<<"\n"<<u<<" "<<dt<<" "<<dt<<"\n";
    }
    return 0;
}

欢迎评论!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值